iptables 是 Linux 系统上强大的防火墙工具,它通过定义一系列的“规则”(Rules)来决定网络数据包是被允许通过还是被拒绝。

核心概念

在写规则之前,必须理解 iptables 的几个核心概念:

  1. : iptables 将规则分类存放在不同的“表”中,最常用的表是 filter 表,它负责过滤数据包(决定放行或拦截),我们主要讨论的就是 filter 表。
  2. : 每个表都包含多个“链”,链是规则的集合,数据包在特定点会被送到链中进行匹配,最常用的链是:
    • INPUT: 处理进入本机的数据包。
    • OUTPUT: 处理从本机发出的数据包。
    • FORWARD: 处理经过本机但不进入本机的数据包(路由器)。
    • 对于访问网站,我们主要关心 INPUT 链(别人访问你的网站)和 OUTPUT 链(你访问别人的网站)。
  3. 规则: 规则是 iptables 的核心,每条规则都包含一个“匹配条件”和一个“目标动作”。
    • 匹配条件: 数据包的目标端口是 80,或源 IP 地址是 192.168.1.100。
    • 目标动作: 当数据包匹配条件后,执行什么操作,最常用的动作有:
      • ACCEPT: 允许数据包通过。
      • DROP: 静默丢弃数据包,发送方不会收到任何错误信息,会感觉连接超时。
      • REJECT: 拒绝数据包,并向发送方发送一个“目标不可达”等错误信息。
      • LOG: 记录日志到 /var/log/messages/var/log/kern.log,但数据包会继续匹配后续规则。

控制外部访问你的网站(服务器端)

假设你的服务器 IP 地址是 0.113.10,网站运行在 80 (HTTP) 和 443 (HTTPS) 端口。

允许访问网站(默认策略)

防火墙的默认策略是 DROPREJECT 所有流量,然后我们只开放需要的端口。

# 1. 清空所有现有规则(谨慎操作!)
iptables -F
iptables -X
# 2. 设置默认策略为拒绝所有进入和发出的数据包
#    (这只是一个示例,OUTPUT 策略设为 ACCEPT)
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT # 通常允许所有出站连接
# 3. 允许本地回环接口(localhost)的通信,很多服务依赖它
iptables -A INPUT -i lo -j ACCEPT
# 4. 允许已建立的和相关的连接(非常重要!)
#    这确保了客户端可以正常与你的网站进行数据交互
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 5. 允许外部访问 80 端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# 6. 允许外部访问 443 端口
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

命令解释:

  • -A INPUT: 在 INPUT 链的末尾添加一条规则。
  • -p tcp: 指定协议为 TCP(HTTP/HTTPS 都基于 TCP)。
  • --dport 80: --destination-port 的缩写,目标端口是 80。
  • -j ACCEPT: 如果匹配,则接受数据包。

禁止访问你的网站

如果你想禁止所有人访问你的网站,最简单的方法是删除上面添加的规则。

# 删除允许 80 端口的规则
iptables -D INPUT -p tcp --dport 80 -j ACCEPT
# 删除允许 443 端口的规则
iptables -D INPUT -p tcp --dport 443 -j ACCEPT

由于默认策略是 DROP,删除了 ACCEPT 规则后,所有访问 80 和 443 端口的请求都会被拒绝。

只允许特定 IP 访问你的网站

假设只允许 IP 168.1.100 访问你的网站。

# 1. 先清空或重置 INPUT 链
iptables -F INPUT
# 2. 设置默认策略为 DROP
iptables -P INPUT DROP
# 3. 允许特定 IP 访问 80 和 443 端口
iptables -A INPUT -p tcp -s 192.168.1.100 --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.1.100 --dport 443 -j ACCEPT
# 4. (可选) 允许本地回环和已建立的连接
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

命令解释:

  • -s 192.168.1.100: --source 的缩写,指定源 IP 地址。

控制你访问外部网站(客户端)

假设你的客户端 IP 是 168.1.50,你想限制它只能访问 example.com

允许访问特定网站

直接用 IP 地址来限制是最可靠的,因为 DNS 可能会被污染或更改。

# 1. 获取 example.com 的 IP 地址
#    假设 example.com 的 IP 是 93.184.216.34
#    nslookup example.com
# 2. 清空 OUTPUT 链(谨慎操作!)
iptables -F OUTPUT
# 3. 设置 OUTPUT 默认策略为 DROP
iptables -P OUTPUT DROP
# 4. 允许访问特定网站的 80 和 443 端口
#    -d 指定目标地址
iptables -A OUTPUT -p tcp -d 93.184.216.34 --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp -d 93.184.216.34 --dport 443 -j ACCEPT
# 5. (可选) 允许访问 DNS 服务器 (UDP 53) 以便解析域名
#    假设 DNS 服务器是 8.8.8.8
iptables -A OUTPUT -p udp -d 8.8.8.8 --dport 53 -j ACCEPT

禁止访问特定网站

如果你想禁止访问 bad-site.com (IP 51.100.10),但允许访问其他所有网站。

# 1. 设置 OUTPUT 默认策略为 ACCEPT
iptables -P OUTPUT ACCEPT
# 2. 在允许所有出站连接的规则之前,先禁止访问 bad-site.com
#    -I 表示在链的开头插入规则
iptables -I OUTPUT -p tcp -d 198.51.100.10 --dport 80 -j DROP
iptables -I OUTPUT -p tcp -d 198.51.100.10 --dport 443 -j DROP

注意: 规则的顺序很重要。-I 在开头插入,-A 在末尾添加,因为 iptables 匹配规则是按顺序进行的,一旦匹配就执行动作,不再继续匹配。


规则的保存与持久化

在大多数现代 Linux 发行版(如 Ubuntu, Debian, CentOS 7+)上,iptables 规则是临时的,重启后会丢失,你需要使用 iptables-persistentnetfilter-persistent 来保存规则。

Ubuntu/Debian:

# 安装
sudo apt-get update
sudo apt-get install iptables-persistent
# 保存当前规则
sudo netfilter-persistent save
# 如果规则已更改,再次保存
sudo netfilter-persistent save

CentOS/RHEL:

# 安装
sudo yum install iptables-services
# 启动服务并设置开机自启
sudo systemctl enable iptables
sudo systemctl start iptables
# 保存当前规则
sudo service iptables save

查看和管理规则

  • 查看规则:
    # 查看所有规则(-n 以数字形式显示,更清晰;-v 显示详细信息)
    sudo iptables -L -nv
  • 查看特定链的规则:
    sudo iptables -L INPUT -nv
  • 删除规则:
    • 按序号删除(推荐,当规则复杂时):
      # 先查看规则和序号
      sudo iptables -L INPUT --line-numbers
      # 假设要删除序号为 3 的规则
      sudo iptables -D INPUT 3
    • 删除(如上文所示):
      sudo iptables -D INPUT -p tcp --dport 80 -j ACCEPT

重要提示

  1. 远程操作风险: 如果你通过 SSH 远程连接服务器,务必不要在清空所有规则或设置默认 DROP 策略之前,就添加一条规则来允许 SSH 连接(通常是 22 端口),否则,你可能会把自己锁在服务器外面。
    # 在设置默认 DROP 策略之前,先允许 SSH
    iptables -A INPUT -p tcp --dport 22 -j ACCEPT
    iptables -P INPUT DROP
  2. 从简单开始: 先从允许所有流量开始,然后逐步添加 DROP 规则来限制,这样更容易排查问题。
  3. 日志记录: 如果不确定规则是否生效,可以使用 LOG 动作来记录被匹配的数据包。
    # 记录所有被 DROP 的 INPUT 包
    iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "IPTABLES-DROP: "
    iptables -A INPUT -j DROP

希望这份详细的指南能帮助你理解和使用 iptables 来管理网站访问!