被 iptables 咬过的几次
iptables 的规则是有顺序的,匹配到第一条就结束。这句话我看了很多遍,但真正记住是付出过代价的。
第一次:把自己的 SSH 关在门外
当时想着「只允许特定 IP 访问 22 端口」,写了这么一条:
iptables -A INPUT -p tcp --dport 22 -j DROP
iptables -A INPUT -p tcp -s 1.2.3.4 --dport 22 -j ACCEPT
然后我就断线了。因为 DROP 在前,所有 22 端口的包在第一条就被丢掉了,第二条永远轮不到。
正确的顺序是放行在前:
iptables -A INPUT -p tcp -s 1.2.3.4 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
按 -A 是追加到末尾。如果要在中间插,得用 -I 加序号。
第二次:DROP 和 REJECT 的区别
一直以为这两个差不多,直到写了个健康检查脚本,它对超时的处理和连接被拒的处理完全不同。
DROP 是把包扔掉,不发任何回应,客户端要一直等到超时。REJECT 会回一个 ICMP 不可达或者 TCP RST,客户端立刻就知道了。
对外面来的扫描,DROP 更好 —— 让扫描器在那儿干等。对自己内部的规则,REJECT 更好调试。
第三次:规则没存下来
调了一下午,重启之后全没了。iptables 的规则默认只存在内核里,重启就清空。
apt install iptables-persistent
iptables-save > /etc/iptables/rules.v4
装完之后它会自动在开机时加载 /etc/iptables/rules.v4。但注意:之后每次改完规则,都要重新 iptables-save 一次,否则下次重启又是旧的。
现在我的习惯
改任何规则之前先 iptables-save 存一份,改完立刻 iptables -L -n --line-numbers 看一眼顺序,确认无误再保存。多花十秒钟,能省掉一次救援。