最近,我决定丢弃那些想要通过端口 80 发出的数据包。看来我的配置有问题,因为一些不需要的数据包被丢弃了。
我的配置摘录:
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -p tcp -s [PUBLIC IP OF MY SERVER] --sport 80 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT
问题 1:第二条规则不是没用的吗,因为我在第一条规则中已经说过我接受所有处于“ESTABLISHED”状态的数据包?
问题2:为什么这两条规则不足以接受以下丢弃的数据包:
Jul 14 18:47:18 [HOSTNAME] kernel: iptables output: IN= OUT=eth0 SRC=[PUBLIC IP OF MY SERVER] DST=[A WWW CLIENT PUBLIC IP] LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=8408 DF PROTO=TCP SPT=80 DPT=50085 WINDOW=123 RES=0x00 ACK FIN URGP=0
Jul 14 18:47:53 [HOSTNAME] kernel: iptables output: IN= OUT=eth0 SRC=[PUBLIC IP OF MY SERVER] DST=[A WWW CLIENT PUBLIC IP] LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=8409 DF PROTO=TCP SPT=80 DPT=50085 WINDOW=123 RES=0x00 ACK FIN URGP=0
Jul 14 18:48:08 [HOSTNAME] kernel: iptables output: IN= OUT=eth0 SRC=[PUBLIC IP OF MY SERVER] DST=[A WWW CLIENT PUBLIC IP] LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=54091 DF PROTO=TCP SPT=80 DPT=25780 WINDOW=16616 RES=0x00 ACK FIN URGP=0
注意:
- 链中没有任何规则可以丢弃数据包。
- 默认策略是 DROP。
编辑 我在看这个帖子,并且还启用了内核对无效数据包的记录:
echo 255 >/proc/sys/net/netfilter/nf_conntrack_log_invalid
现在看来我遇到了几种错误:
Jul 14 22:00:40 [HOSTNAME] kernel: nf_ct_tcp: invalid RST IN= OUT= SRC=[ONE_CLIENT_IP] DST=[SERVER_IP] LEN=40 TOS=0x00 PREC=0x00 TTL=49 ID=47149 PROTO=TCP SPT=993 DPT=51364 SEQ=1043042446 ACK=0 WINDOW=0 RES=0x00 RST URGP=0
Jul 14 21:57:11 [HOSTNAME] kernel: nf_ct_tcp: invalid packet ignored in state ESTABLISHED IN= OUT= SRC=[SERVER_IP] DST=[ONE_CLIENT_IP] LEN=48 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=3782 SEQ=474588492 ACK=2243291425 WINDOW=14600 RES=0x00 ACK SYN URGP=0 OPT (020405B401010402)
Jul 14 21:57:25 [HOSTNAME] kernel: nf_ct_tcp: invalid packet ignored in state LAST_ACK IN= OUT= SRC=[SERVER_IP] DST=[ONE_CLIENT_IP] LEN=48 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=3782 SEQ=474588492 ACK=2243291425 WINDOW=14600 RES=0x00 ACK SYN URGP=0 OPT (020405B401010402)
Jul 14 21:57:41 [HOSTNAME] kernel: nf_ct_tcp: invalid packet ignored in state TIME_WAIT IN= OUT= SRC=[SERVER_IP] DST=[ONE_CLIENT_IP] LEN=48 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=3782 SEQ=474588492 ACK=2243291425 WINDOW=14600 RES=0x00 ACK SYN URGP=0 OPT (020405B401010402)
Jul 14 21:58:52 [HOSTNAME] kernel: nf_ct_tcp: invalid packet ignored in state SYN_RECV IN= OUT= SRC=[SERVER_IP] DST=[ONE_CLIENT_IP] LEN=48 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=50488 SEQ=3804975135 ACK=229029122 WINDOW=14600 RES=0x00 ACK SYN URGP=0 OPT (020405B401010402)
答案1
(实际上我在其他地方做过这个回答,我以为是同一个网站)
根据这些:
http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm
http://www.iptables.info/en/connection-state.html(不是最新的)
有可能客户端(也许是移动客户端)首先关闭,没有等待最后的 FIN/ACK 并且从未发送其最后的 ACK,或者服务器应答得太晚并且客户端本身受防火墙保护或任何其他响应缓慢的情况...因此服务器会重试,超出计时器(sysctl net.netfilter.nf_conntrack_tcp_timeout_last_ack
)但 netfilter 在真正的 tcp 堆栈丢弃它之前已经丢弃了该状态。
您应该进行跟踪并查看是否有重复的数据包。
第二条规则是第一条规则的子集,因此毫无用处。尝试增加各种tcp_超时设置(sysctl -w net.netfilter....
或echo XX > /proc/sys/net/netfilter/...
),看看这些日志是否消失。我过去出于类似原因设置了此选项,它“解决”了一些神秘的 netfilter 日志。这可能会增加 conntrack 内存使用量。
答案2
1)如果您有第一个,那么第二个似乎就没用了。
2) 现在。你为什么要默认对 OUTPUT 使用 DROP?你不相信自己?我会默认使用 ACCEPT。只需将你的规则应用于 INPUT 链,默认使用 DROP。在 INPUT 链中使用适当的规则并默认使用 DROP,iptables 将很好地保护你的服务器。如果你没有进行非常特殊的安全设置,为 OUTPUT 创建这样的策略似乎太过分了。
答案3
在三次 TCP 握手完成之前,连接尚未“建立”。握手需要客户端发送一个SYN
数据包,您返回一个SYN+ACK
数据包,然后客户端返回一个ACK
数据包。但是,您将阻止SYN+ACK
传出的数据包。
更好的做法是允许所有OUTPUT
符合 的数据包-p tcp --sport 80 --dport 1024:65535
。您还可以进一步限制下限;IANA 建议将端口 41952 及以上用作随机源端口,但您可能会注意到许多客户端并不合规。这样的规则将允许任何响应端口 80 连接的流量,其中客户端上的端口不是特权端口(并将阻止恶意软件在 80 或 443 上呼叫)。
如果您更喜欢使用连接状态作为规则,您也可以允许源端口 80 上的传出数据包具有状态ESTABLISHED,RELATED,SYN_RECV
(在您的配置中,您可以直接使用,SYN_RECV
因为第一条规则会处理它)。这将允许传出设置SYN+ACK
传出连接。
无效数据包似乎与它们是数据包有关SYN+ACK
,但连接并未等待建立。这可能是与问题无关的产物,无需担心。