关于ipset结合iptables规则生效异常及简化实现的技术问询
我用脚本维护一个名为ipsum的ipset地址集合,一开始想通过单条规则阻断这个集合里的地址访问所有端口,于是加了这条规则:
/sbin/iptables -I INPUT -m set --match-set ipsum src -j DROP
但实际测试发现,这条规则没法阻断ipsum里的地址访问80和443端口,必须额外添加两条FORWARD链的规则才能生效:
/sbin/iptables -A FORWARD -p tcp --dport 443 -m set --match-set ipsum dst -j DROP /sbin/iptables -A FORWARD -p tcp --dport 80 -m set --match-set ipsum dst -j DROP
我已经验证过这两条规则确实能正常阻断目标端口,但完全搞不懂为什么最初的INPUT链规则达不到预期效果。
环境补充:我同时在用ufw
ufw里配置了允许80/443端口的访问,对应的iptables规则在ufw-user-input链里:
Chain ufw-user-input (1 references) target prot opt source destination ACCEPT tcp -- anywhere anywhere tcp dpt:http ACCEPT udp -- anywhere anywhere udp dpt:80 ACCEPT tcp -- anywhere anywhere tcp dpt:https ACCEPT udp -- anywhere anywhere udp dpt:443
我一开始猜测是规则执行顺序的问题,但如果ufw的规则优先级更高的话,我后来加的FORWARD链规则应该不会生效才对,可实际它确实起作用了,这就让我彻底懵了。
核心需求:用单条规则实现全端口阻断
我想找一个更优雅的方式,用单条规则替代现有规则,实现阻断ipsum集合里的地址访问所有端口。我试过用这条规则做临时 workaround,但感觉很不优雅,而且这条规则在链列表里根本找不到,等于没生效:
/sbin/iptables -A FORWARD -p tcp --dport 0:65535 -m set --match-set ipsum dst -j DROP
FORWARD链的完整输出
我用iptables -L FORWARD查了当前的链状态,输出如下(有点长,麻烦各位耐心看一下):
Chain FORWARD (policy DROP) target prot opt source destination DOCKER-USER all -- anywhere anywhere DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED DOCKER all -- anywhere anywhere ACCEPT all -- anywhere anywhere ACCEPT all -- anywhere anywhere ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED DOCKER all -- anywhere anywhere ACCEPT all -- anywhere anywhere ACCEPT all -- anywhere anywhere ufw-before-logging-forward all -- anywhere anywhere ufw-before-forward all -- anywhere anywhere ufw-after-forward all -- anywhere anywhere ufw-after-logging-forward all -- anywhere anywhere ufw-reject-forward all -- anywhere anywhere ufw-track-forward all -- anywhere anywhere DROP tcp -- anywhere anywhere tcp dpt:https match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:http match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:https match-set fireh dst DROP tcp -- anywhere anywhere tcp dpt:http match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:https match-set blockde dst DROP tcp -- anywhere anywhere tcp dpt:http match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:http match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:https match-set tornodes dst DROP tcp -- anywhere anywhere tcp dpt:http match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:https match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:http match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:https match-set fireh dst DROP tcp -- anywhere anywhere tcp dpt:http match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:https match-set blockde dst DROP tcp -- anywhere anywhere tcp dpt:http match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:http match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:https match-set tornodes dst DROP tcp -- anywhere anywhere tcp dpt:http match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:https match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:http match-set ipsum dst DROP tcp -- anywhere anywhere tcp dpt:https match-set fireh dst DROP tcp -- anywhere anywhere tcp dpt:http match-set fireh dst DROP tcp -- anywhere anywhere tcp dpt:https match-set blockde dst DROP tcp -- anywhere anywhere tcp dpt:http match-set blockde dst DROP tcp -- anywhere anywhere tcp dpt:https match-set tornodes dst DROP tcp -- anywhere anywhere tcp dpt:http match-set tornodes dst DROP tcp -- anywhere anywhere tcp dpt:https match-set russia dst DROP tcp -- anywhere anywhere tcp dpt:http match-set russia dst DROP tcp -- anywhere anywhere tcp match-set ipsum dst DROP tcp -- anywhere anywhere tcp match-set ipsum dst DROP tcp -- anywhere anywhere tcp match-set fireh dst DROP tcp -- anywhere anywhere tcp match-set blockde dst DROP tcp -- anywhere anywhere tcp match-set tornodes dst DROP tcp -- anywhere anywhere tcp match-set russia dst DROP tcp -- anywhere anywhere tcp match-set ipsum dst DROP tcp -- anywhere anywhere tcp match-set fireh dst DROP tcp -- anywhere anywhere tcp match-set blockde dst DROP tcp -- anywhere anywhere tcp match-set tornodes dst DROP tcp -- anywhere anywhere tcp match-set ipsum dst DROP tcp -- anywhere anywhere tcp match-set fireh dst DROP tcp -- anywhere anywhere tcp match-set blockde dst DROP tcp -- anywhere anywhere tcp match-set tornodes dst DROP all -- anywhere anywhere match-set ipsum src DROP tcp -- anywhere anywhere tcp match-set ipsum dst DROP tcp -- anywhere anywhere tcp match-set fireh dst DROP tcp -- anywhere anywhere tcp match-set blockde dst DROP tcp -- anywhere anywhere tcp match-set tornodes dst DROP all -- anywhere anywhere match-set tornodes src
从输出里能看到,我尝试的全端口阻断规则根本没出现在链里,等于白加了。
额外的疑惑:src和dst的用法搞混了?
我原本的理解是:src对应外部发起请求的源地址(incoming流量),dst对应本地发出去的请求的目标地址(outgoing流量),但实际测试发现iptables -A FORWARD -p tcp --dport 80 -m set --match-set ipsum dst -j DROP这条规则居然能阻断外部对80端口的访问,这和我理解的完全相反。
我还试过添加这条规则:
iptables -A FORWARD -m set --match-set ipsum src -j DROP
对应的链条目是DROP all -- anywhere anywhere match-set ipsum src,但这条规则好像没起到预期的阻断作用。我是不是完全搞反了src和dst的用法?
真心希望各位能帮忙梳理清楚问题,给出更优雅的单规则实现方案,感谢大家!
备注:内容来源于stack exchange,提问作者airdogvan

