使用iptraf,tcpdump和wireshark我可以看到一个SYN数据包进入,但只有ACK FLAG被设置在回复数据包中。
我正在运行内核2.6.36的Debian 5
我closures了window_scaling和tcp_timestamps,tcp_tw_recycle和tcp_tw_reuse:
cat /etc/sysctl.conf net.ipv4.tcp_tw_recycle = 0 net.ipv4.tcp_tw_reuse = 0 net.ipv4.tcp_window_scaling = 0 net.ipv4.tcp_timestamps = 0
我附上了wireshark输出的图像。
输出到netstat
netstat -natu | grep '72.23.130.104' tcp 0 0 97.107.134.212:18000 72.23.130.104:42905 SYN_RECV
我一直在尽一切可能find一个解决scheme,还没有找出问题,所以任何帮助/build议非常感谢。
更新1:我已经设置了tcp_syncookies = 0,并且注意到我现在每回复50个SYN请求就有1个SYN + ACK。 尝试连接的主机每秒发送一次SYN请求。
PCAP文件
遇到同样的问题后,我终于find了根本原因。
在Linux上,当套接字在TIME_WAIT和一个新的SYN追加(对于同一对ip / port src,ip / port dest)时,内核检查SYN的SEQ编号是否小于最后接收到的SEQ这个sockets。
(PS:在附加到这个问题的wireshark输出的图像中,seq编号显示为相对的,如果你不把它们设置为绝对的,你不能看到问题。捕获将不得不显示旧的会话还能够比较SEQ号码)
这种行为就像这样,因为在TCP开始的时候,增量的计算机产生的SEQ号码几乎不可能接收到一个仍然在TIME_WAIT中的前一个套接字的SEQ号<的序列号。
计算机带宽的增加使其几乎不可能变为罕见。 但是这里最重要的是现在大多数系统使用随机ISN(初始SEQ编号)来提高安全性。 所以没有什么能够阻止新套接字的SEQ号a大于前一个的SEQ号。
每个操作系统使用不同的algorithm或多或less是安全的,以避免这个问题http://www.bsdcan.org/2006/papers/ImprovingTCPIP.pdf提供了一个很好的问题。
还有最后一个棘手的事情……所以内核会发送一个与旧会话相关的ACK,然后呢? 客户端操作系统应该收到ACK(前一个会话),不理解,因为对于客户端会话closures,发送一个RST。 当服务器收到这个RST时,它会立即清除套接字(所以不再在TIME_WAIT中)。 在他的一面,客户端正在等待一个SYN / ACK,因为它没有得到它,它会发送一个新的SYN。 同时RST已经被发送,会话在服务器上被清除,所以这个辅助SYN将起作用,并且服务器将回复SYN / ACK等等。
所以正常的行为是连接应该工作,但是被延迟一秒(直到发送辅助SYN)。 在Jeff的情况下,他在评论中说他使用的是Fortinet防火墙,这些防火墙(默认情况下)会丢弃与旧会话有关的ACK(因为防火墙看不到有关ACK的开放会话),所以客户端不会发送任何RST并且服务器不能从TIME_WAIT状态中清除会话(当然在TIME_WAIT计时器结束时除外)。 fortinet上的“set anti-replay loose”命令可以允许这个ACK包被转发而不是丢弃。
看来,97.107.134.212已经认为有一个联系(72.23.130.104:42905, 97.107.134.212:18000) 。
当72.23.130.104:42905发送它的SYN包时,它的序列号是246811966.接下来应该是一个带有自己的SEQ号码和一个ACK值为246811967的SYN / ACK包。
但是它发送了一个ACK = SEQ ID = 1736793629,ACK = 172352206。 这些可能是早期连接的价值。
任何新的连接尝试应该来自不同的端口号…是发生? Wireshark在pkt#11中指出:“重用TCP端口号”。
看起来问题是发件人。
FWIW,我可以连接好:
1 0.000000 192.168.0.135 97.107.134.212 TCP 45883 > biimenu [SYN] Seq=809402803 Win=14600 Len=0 MSS=1460 SACK_PERM=1 TSV=2319725 TSER=0 WS=7 2 0.022525 97.107.134.212 192.168.0.135 TCP biimenu > 45883 [SYN, ACK] Seq=4293896301 Ack=809402804 Win=14600 Len=0 MSS=1360 SACK_PERM=1 3 0.022553 192.168.0.135 97.107.134.212 TCP 45883 > biimenu [ACK] Seq=809402804 Ack=4293896302 Win=14600 Len=0
有一次我看到过这种情况,这是因为出站和入站数据包在networking上采取了不同的路由,并且在入站站点有一个有状态的连接跟踪设备。 由于该设备(我的情况下是一个负载均衡器,但它可能很容易成为防火墙)从来没有看到最初的SYN,所以SYN-ACK被误认为是虚假的。
它不仅仅是不对称,因为我们也丢失了一个外出的数据包:
SYN消失,但是我们看不到传入的SYN-ACK, 或者从本地服务器传出的ACK。 因此,其他东西必须代理这两个数据包,然后我们看到传入的ACK – 这实际上是序列中的第四个数据包。
我的猜测是广域网加速器configuration错误。
我会检查一些事情:
你的主机是多宿主的(例如,你有多个以太网接口?) – 如果这样你的路由可能会搞砸。 最简单的方法来testing这将是禁用您的辅助界面(S),看看问题是否消失。
其他要检查的是iptables(或其他防火墙)是否启用。 服务iptables停止将closures它,直到下一次重新启动 – 如果这解决了这个问题,那么你需要调整你的iptables设置。
另外,如果您的接口上启用了IPv6,有时会通过ipv4路由,但不会通过ipv6。 发生这种情况时,ipv6路由是“默认”,你的数据包可以通过错误的地址(即使在正确的接口)。 尝试禁用ipv6,看看是否是这个问题。