客户端网络地址转换 (NAT) 防火墙后面的各种工作站正在将 TCP 数据包上的时间戳信息发送到我们的服务器。来自许多工作站的数据包从 NAT 设备后面到达时带有无序的时间戳。当它们到达我们的服务器时(在某些情况下是在同一端口上),服务器无法区分这些数据包与从同一端口和同一客户端 IP(NAT 设备)到达的其他数据包。
服务器将时间戳顺序错误的数据包解释为属于已完成的连接,然后忽略该数据包 - 但在这种情况下不应该这样做。这些是来自 NAT 设备后面的工作站的合法数据包。丢弃具有旧时间戳值的数据包是 TCP 的一项设计功能,称为 PAWS(http://www.ietf.org/rfc/rfc1323.txt,防止包装序列)-服务器只是假设数据包是旧的,并且已经处理了连接。
为了解决这个问题,我们禁用了服务器上的时间戳设置。但是 - 这种情况的最佳做法是什么?是否应该禁用所有服务器的时间戳支持?还是应该删除或重写所有 NAT 设备中的时间戳值?还是?
答案1
源端口是 TCP 连接的附加识别特征,NAT 设备后面的任何两个连接都不应分配相同的源端口 - 客户端永远不会干扰彼此的连接,除非坏的 NAT 设备为它们分配了相同的源端口。
PAWS 不应丢弃所需的数据包,而应丢弃重发的重复数据包 - 无序交付不会更新时间戳底线。时间值是从最后一个按序分段复制的;序列号较高的数据包(即所需的数据包)应始终比序列号较低的数据包具有更高的时间戳。
如果顺序正确但时间戳较低,则说明 TCP 客户端行为不当 - 并且如果由于某种异常,PAWS 丢弃了好的、按顺序的数据包,则客户端应该使用新的时间戳重新发送,以恢复因丢弃而导致的任何问题。
您看到的哪些行为导致了此问题?
答案2
就我而言,以下命令修复了 Linux 服务器缺少 SYN/ACK 回复的问题:
sysctl -w net.ipv4.tcp_tw_recycle=0
我认为这比禁用 TCP 时间戳更正确,因为 TCP 时间戳毕竟是有用的(PAWS、窗口缩放等)。
文档中tcp_tw_recycle
明确指出不建议启用它,因为许多 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.