iptables 是 Linux 系统上强大的防火墙工具,它通过定义一系列的“规则”(Rules)来决定网络数据包是被允许通过还是被拒绝。
核心概念
在写规则之前,必须理解 iptables 的几个核心概念:
- 表:
iptables将规则分类存放在不同的“表”中,最常用的表是filter表,它负责过滤数据包(决定放行或拦截),我们主要讨论的就是filter表。 - 链: 每个表都包含多个“链”,链是规则的集合,数据包在特定点会被送到链中进行匹配,最常用的链是:
INPUT: 处理进入本机的数据包。OUTPUT: 处理从本机发出的数据包。FORWARD: 处理经过本机但不进入本机的数据包(路由器)。- 对于访问网站,我们主要关心
INPUT链(别人访问你的网站)和OUTPUT链(你访问别人的网站)。
- 规则: 规则是
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) 端口。
允许访问网站(默认策略)
防火墙的默认策略是 DROP 或 REJECT 所有流量,然后我们只开放需要的端口。
# 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-persistent 或 netfilter-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
- 按序号删除(推荐,当规则复杂时):
重要提示
- 远程操作风险: 如果你通过 SSH 远程连接服务器,务必不要在清空所有规则或设置默认
DROP策略之前,就添加一条规则来允许 SSH 连接(通常是 22 端口),否则,你可能会把自己锁在服务器外面。# 在设置默认 DROP 策略之前,先允许 SSH iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -P INPUT DROP
- 从简单开始: 先从允许所有流量开始,然后逐步添加
DROP规则来限制,这样更容易排查问题。 - 日志记录: 如果不确定规则是否生效,可以使用
LOG动作来记录被匹配的数据包。# 记录所有被 DROP 的 INPUT 包 iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "IPTABLES-DROP: " iptables -A INPUT -j DROP
希望这份详细的指南能帮助你理解和使用 iptables 来管理网站访问!
