random tips on coding, ops, ...

iptables recent 模块配置

假设有如下需求,需要对来自每个 IP 的 SSH 连接尝试频率做限制, 例如 10 次/每分钟。netfilter 里 recent 模块正好可以实现该需求。 但在具体的实现过程中走过一些弯路,本文尝试做一个总结如下。

如下两种配置方式在命令行上的区别为顺序完全相反。 考虑如下两种配置方式的差别在哪?

iptables -A INPUT -i eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth1 -p tcp -m multiport --dports 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 10 --rttl --name SSH --rsource -j DROP
iptables -A INPUT -i eth1 -p tcp -m multiport --dports 22 -m conntrack --ctstate NEW -m recent --set --name SSH --rsource -j ACCEPT
iptables -A INPUT -i eth1 -p tcp -m multiport --dports 22 -m conntrack --ctstate NEW -m recent --set --name SSH --rsource -j ACCEPT
iptables -A INPUT -i eth1 -p tcp -m multiport --dports 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 10 --rttl --name SSH --rsource -j DROP
iptables -A INPUT -i eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

在实现效果上前者会允许一分钟内 10 次新建连接(可以使用 nc 测试),第 11 次请求会被 drop;而后者则是丢弃第 10 次请求。原因体现在连接率的原始计算数据 是由 “-m recent –set –name SSH …” 这条规则来更新的,如果 DROP 规则在这 之前,则率的判断只有在下一次新建请求到达时才会匹配。

对后一种配置方式,如果 “–ctstate RELATED,ESTABLISHED -j ACCEPT” 规则的位置在 drop 之前,会导致 drop 规则永远无法匹配上。这是因为连接状态 处于 NEW 时被放过,回应包返回后状态就会改变为 ESTABLISHED。状态变迁的细节信息可 以参考 The state machine

最后说明一下,recent 模块的 –rcheck 和 –update 参数的区别是后者会更新最后到达 包的时间戳,也就是说,所有被 drop 的包依然参与率的计算。


comments powered by Disqus