防火墙规则按自上而下顺序匹配,命中即停止;关键在位置而非存在——iptables看行号与drop/accept顺序,firewalld重priority,ufw需enable并查编号,log日志验证实际匹配路径。

先确认当前生效的规则链和顺序
防火墙规则按自上而下顺序匹配,一旦命中就停止检查。所以“规则存在”不等于“规则生效”。重点不是看有没有放行语句,而是它在链中的位置是否足够靠前。
对 iptables:运行 sudo iptables -L INPUT -n --line-numbers -v,注意三件事:
– 每条规则前的行号(1、2、3…)代表执行顺序
– 是否有 REJECT 或 DROP 规则出现在你的 ACCEPT 规则之前
– -v 参数显示的 packet 和 byte 计数:若某条 DROP 规则计数持续增长,说明它正在拦截流量
对 firewalld:它底层也转为 nftables 或 iptables,但直接查规则顺序不直观。应改用 firewall-cmd --list-all 查 ports 列表,并配合 firewall-cmd --list-rich-rules 看是否有带 priority 的 rich rule——priority 值越小越优先,低于 0 的规则可能插在默认策略之前。
识别典型顺序陷阱
以下几种配置看似合理,实则因顺序导致端口被静默拦截:
- 在末尾加了 -A INPUT -j REJECT 或 -A INPUT -j DROP,但没在前面插入对应 ACCEPT 规则 → 所有未明确放行的端口全被拒
- 先写了 -I INPUT -s 192.168.1.0/24 -j ACCEPT,又在后面加了 -I INPUT -p tcp --dport 80 -j ACCEPT → 实际上第二条被插入到第一行,但若第一条是更宽泛的拒绝规则,仍可能覆盖
- firewalld 中用了 rich rule 限制来源 IP,但没设 priority,系统按字母序或插入序加载,可能晚于默认 zone 的 DROP 策略
- ufw 默认策略是 deny incoming,若只执行 ufw allow 22 却忘了 ufw enable,规则根本没激活
验证顺序影响的实操方法
不要只看配置,要观察真实匹配行为:
– 在疑似被拦截的端口上插入一条 LOG 规则(iptables):
sudo iptables -I INPUT -p tcp --dport 80 -j LOG --log-prefix "http-in: "
再紧跟着插入 ACCEPT:
sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT
然后从外部 nc -zv ip 80,再查日志:
journalctl -k | grep "http-in" | tail -5 —— 若看到日志但连接仍不通,说明 ACCEPT 后面还有更早的 DROP 在起作用
– 对 firewalld,开启全局拒绝日志:
sudo firewall-cmd --set-log-denied=all
触发一次访问后,查:
journalctl -u firewalld --since "2 minutes ago" | grep "deny"
若日志里出现目标端口但你确信已添加 allow 规则,大概率是规则没生效(比如漏了 --permanent 或没 reload)或被更高优先级 rich rule 覆盖
修复与固化顺序
修正顺序的核心原则:让允许规则尽可能靠前,拒绝兜底规则放在最后。
- iptables:用 -I INPUT 1 插入最顶端;用 --line-numbers 定位后,用 -D INPUT X 删除错误位置的规则,再重新插入
- firewalld rich rule:显式指定 priority=0(最高优先),例如:
firewall-cmd --add-rich-rule='rule priority=0 family="ipv4" source address="10.0.0.0/8" port port="3306" protocol="tcp" accept' - ufw:规则按添加顺序排列,可用 ufw status numbered 查序号,用 ufw delete N 删除后再重加
- 所有修改后,别忘了持久化:
iptables → iptables-save > /etc/iptables/rules.v4
firewalld → 加 --permanent 并执行 firewall-cmd --reload
ufw → 规则默认持久,但需确认 ufw status 显示为 active











