iptables 规则添加后没有报错却不生效,最常见的原因是规则顺序被前置规则覆盖、链选择错误或者规则未持久化。建议优先查看规则计数器是否增长,并确认规则是否添加到了正确的链和位置。
先说结论:大部分不生效问题源于匹配顺序或服务冲突,而非规则语法错误。
- 先确认:服务状态与链方向
- 先处理:规则顺序与持久化
- 再验证:流量匹配计数
命令速用版
快速查看规则列表及计数器:
iptables -L -n -v `--line-numbers`
保存规则以防重启丢失(区分发行版):
# CentOS 7+ (需确认路径) iptables-save > /etc/sysconfig/iptables # Ubuntu/Debian (需安装 netfilter-persistent) netfilter-persistent save # 或直接保存 iptables-save > /etc/iptables/rules.v4
检查服务状态:
systemctl status iptables
为什么会这样
iptables 的工作机制是“自上而下匹配,命中即止”。如果前面有一条规则已经 ACCEPT 或 DROP 了数据包,后面的规则即使写得再正确也不会被执行。此外,iptables 命令修改的是内存中的规则,重启后会丢失,除非手动保存。某些新系统默认使用 nftables 后端或 firewalld 管理,直接操作 iptables 可能被覆盖。
分步处理
1. 检查服务状态:确认 iptables 服务正在运行,未处于 inactive 状态。
systemctl status iptables
2. 检查规则顺序:使用带行号的列表命令,确认新规则是否在拒绝规则之前。如需调整,使用 -I 参数插入到指定位置。
# 示例:将允许 80 端口的规则插入到 INPUT 链第 1 行 iptables -I INPUT 1 -p tcp `--dport` 80 -j ACCEPT
3. 确认链选择:确保规则加在正确的链上(如本机流量用 INPUT,转发流量用 FORWARD)。
4. 排查冲突:检查是否运行了 firewalld 或 ufw,避免多重防火墙管理导致冲突。
systemctl status firewalld systemctl status ufw
5. 持久化保存:执行保存命令,将内存规则写入配置文件。
⚠️ 风险警告:修改默认策略为 DROP 前,务必先添加允许 SSH 端口的规则,否则可能导致远程失联。
怎么验证是否生效
1. 观察计数器:查看规则列表中的数据包计数器和字节计数器是否随流量增加。如果计数不变,说明流量未匹配到该规则。
2. 添加日志规则:在目标规则前添加 LOG 规则,查看系统日志确认流量是否到达。
iptables -I INPUT 1 -p tcp `--dport` 80 -j LOG `--log-prefix` "IPTABLES-HTTP: " tail -f /var/log/messages # 或 /var/log/syslog
3. 抓包验证:配合 tcpdump 抓包确认流量是否到达网卡。
tcpdump -i eth0 -n port 80
常见坑
1. 默认策略为 DROP 时,未添加允许规则会导致连通性中断。
2. NAT 表与 Filter 表混淆,端口转发规则需写在 NAT 表(-t nat)。
3. 状态匹配缺失,未指定 NEW 状态可能导致回包被拦截,建议配合 -m state `--state` NEW,ESTABLISHED 使用。
4. 云主机安全组拦截,即使本机 iptables 放行,云厂商的安全组策略也可能拦截流量。