客户端networking地址转换(NAT)防火墙后面的各种工作站正在将TCP数据包的时间戳信息发送到我们的服务器。 来自多个工作站的数据包在NAT设备后面按顺序发送时间戳。 当他们到达我们的服务器时(在某些情况下在同一个端口上),服务器不能将这些数据包与其他到达同一端口和同一客户端IP(NAT设备)的数据包区分开来。
服务器将带有无序时间戳的数据包解释为属于已经完成的连接,然后忽略数据包 – 但在这种情况下不应该是这样。 这些是来自NAT设备后面工作站的合法数据包。 丢弃具有旧时间戳值的数据包是TCP的一个devise特性,称为PAWS( http://www.ietf.org/rfc/rfc1323.txt,Protect Against Wrapped Sequences) – 服务器只是假定数据包是旧的,已经处理了连接。
要解决这个问题,我们禁用了服务器上的时间戳设置。 但是 – 这种情况的最佳做法是什么? 所有的服务器是否应该禁用时间戳? 还是应该所有的NAT设备删除或重写时间戳值? 要么?
源端口是TCP连接的附加标识特性,NAT设备后面的两个连接不应该分配相同的源端口 – 客户端永远不会干涉对方的连接,除非它们被不良NAT设备赋予相同的源端口。
PAWS不应该丢弃所需的数据包,只是重复发送 – 无序发送不会更新时间戳底。 时间值是从最后一个按顺序段中复制的; 具有较高序列号的数据包(即,需要的数据包)应该总是具有比具有较低序列号的数据包更高的时间戳。
如果顺序正确但时间戳较低,那么TCP客户端就会行为不端 – 如果某些怪异的PAWS丢掉了好的顺序数据包,则客户端应重新发送一个新的时间戳,从任何时间戳恢复丢弃造成的问题。
你看到什么行为导致你这个问题?
在我的情况下,以下命令解决了从Linux服务器丢失SYN / ACK答复的问题:
sysctl -w net.ipv4.tcp_tw_recycle=0
我认为这比禁用TCP时间戳更正确,因为TCP时间戳毕竟是有用的(PAWS,窗口缩放等)。
关于tcp_tw_recycle的文档明确指出,不build议启用它,因为许多NAT路由器保留时间戳,因此PAWS开始使用,因为来自相同IP的时间戳不一致。
tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4) Enable fast recycling of TIME_WAIT sockets. Enabling this option is not recommended for devices communicating with the general Internet or using NAT (Network Address Translation). Since some NAT gateways pass through IP timestamp values, one IP can appear to have non-increasing timestamps. See RFC 1323 (PAWS), RFC 6191.