Linux 无法解释 ACK,不断重新发送 SYN+ACK

Bar*_*iet 5 networking linux firewall iptables

以下是发生问题的wireshark转储,IP地址替换为“客户端”和“服务器”:

4414.229553  client -> server TCP 62464 > http [SYN] Seq=0 Win=65535 Len=0 MSS=1452 WS=3 TSV=116730231 TSER=0
4414.229633 server -> client  TCP http > 62464 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=2406364374 TSER=116730231 WS=6
4414.263330  client -> server TCP 62464 > http [ACK] Seq=1 Ack=1 Win=524280 Len=0 TSV=116730231 TSER=2406364374
4418.812859 server -> client  TCP http > 62464 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=2406365520 TSER=116730231 WS=6
4418.892176  client -> server TCP [TCP Dup ACK 778#1] 62464 > http [ACK] Seq=1 Ack=1 Win=524280 Len=0 TSV=116730278 TSER=2406365520
4424.812864 server -> client  TCP http > 62464 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=2406367020 TSER=116730278 WS=6
4424.891240  client -> server TCP [TCP Dup ACK 778#2] 62464 > http [ACK] Seq=1 Ack=1 Win=524280 Len=0 TSV=116730337 TSER=2406367020
Run Code Online (Sandbox Code Playgroud)

所以正常的 SYN、SYN+ACK、ACK 序列似乎发生了,除了服务器似乎没有解释 ACK。相反,它不断重新发送 SYN+ACK,客户端尽职尽责地使用先前 ACK 的副本进行响应。我不明白这怎么会发生。

我注意到了这个问题,因为 iptables 连接跟踪会考虑这些已建立的连接并将它们保留在内存中长达 120 小时的超时。我有一些防火墙规则来防止大量并发连接,人们正在达到限制,而实际上没有那么多连接处于活动状态。该netstat命令不显示这些幻象连接。

其他信息:

服务器是一个标准的 debian lenny 系统,带有一个股票内核:

Linux tb 2.6.26-2-686 #1 SMP Wed Aug 19 06:06:52 UTC 2009 i686 GNU/Linux
Run Code Online (Sandbox Code Playgroud)

跑步:

Apache/2.2.9 (Debian) mod_ssl/2.2.9 OpenSSL/0.9.8g
Run Code Online (Sandbox Code Playgroud)

我没有客户端上的所有信息(我无法在本地复制),但它是运行 Chrome 浏览器的 Mac。

我没有任何与 ACK 数据包混淆的防火墙规则。基本上我只过滤 SYN 数据包,允许所有其他 TCP 数据包通过。所以我实际上并没有将连接跟踪用于防火墙,除了计算并发连接数以及与其他数据包类型相比的 TCP 建立数据包的一些图形之外。

编辑:我的 iptables 规则与 TCP 端口 80 相关:

iptables -P INPUT ACCEPT
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 50 -j LOGDROP-CONN
iptables -A INPUT -p tcp --syn -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p tcp --syn -j REJECT --reject-with tcp-reset
iptables -A LOGDROP-CONN -m limit --limit 1/minute --limit-burst 1 -j LOG --log-prefix "ConConn "
iptables -A LOGDROP-CONN -j DROP
Run Code Online (Sandbox Code Playgroud)

编辑 2:另一个转储,这次使用 tcpdump -vv:

16:05:52.999525 IP (tos 0x0, ttl 55, id 46466, offset 0, flags [DF], proto TCP (6), length 64) client.50538 > server.www: S, cksum 0x4429 (correct), 38417001:38417001(0) win 65535 <mss 1452,nop,wscale 3,nop,nop,timestamp 117224762 0,sackOK,eol>
16:05:52.999580 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) server.www > client.50538: S, cksum 0xa2ab (correct), 3062713115:3062713115(0) ack 38417002 win 5792 <mss 1460,sackOK,timestamp 2418739698 117224762,nop,wscale 6>
16:05:53.321788 IP (tos 0x0, ttl 55, id 24299, offset 0, flags [DF], proto TCP (6), length 52) client.50538 > server.www: ., cksum 0xe813 (correct), 1:1(0) ack 1 win 65535 <nop,nop,timestamp 117224765 2418739698>
16:05:56.252697 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) server.www > client.50538: S, cksum 0x9f7a (correct), 3062713115:3062713115(0) ack 38417002 win 5792 <mss 1460,sackOK,timestamp 2418740512 117224765,nop,wscale 6>
16:05:56.277250 IP (tos 0x0, ttl 55, id 15533, offset 0, flags [DF], proto TCP (6), length 52) client.50538 > server.www: ., cksum 0xe4c4 (correct), 1:1(0) ack 1 win 65535 <nop,nop,timestamp 117224798 2418740512>
Run Code Online (Sandbox Code Playgroud)

Paw*_*cki 2

我会用暴力来解决。首先我会尝试它是否可以在 iptables 停止的情况下工作。如果是的话,那么它就是 iptables 中的东西。

然后我会一一添加规则并观察哪一条导致连接失败。然后我会遵循这个规则,直到它达到我想要的效果,而不会完全扰乱交通。

如果 iptables 停止后它不起作用,那么它就会开始变得非常奇怪。