2017 年 3 月,内核主线将 TCP Metrics
表项中的时间戳缓存,补丁详见 patch—tcp: remove per-destination timestamp cache
struct tcp_metrics_block {
struct inetpeer_addr tcpm_saddr;
struct inetpeer_addr tcpm_daddr;
unsigned long tcpm_stamp;
- u32 tcpm_ts;
- u32 tcpm_ts_stamp;
u32 tcpm_lock;
u32 tcpm_vals[TCP_METRIC_MAX_KERNEL + 1];
与之一起修改的,还有 tcp: remove tcp_tw_recycle。tcp_tw_recycle
机制是用于内核快速回收 TIME_WAIT 状态的套接字。但是当网络中存在 NAT 设备时,该机制反而可能会导致 NAT 设备背后的客户端难以连接上服务器。
这样的问题实在太多了!网络上随便一搜就是
No response to some SYN packets when timestamps are enabled
Why would a server not send a SYN/ACK packet in response to a SYN packet
why-does-my-linux-box-fail-to-send-syn-ack-until-after-eight-syns-have-arrived?
导致这些问题的原因是服务器收到的 SYN 报文中携带的时间戳早于之前已经收到的 FIN 报文的时间戳,于是服务器认为该 SYN 报文是由于网络阻塞迟到的旧连接的 SYN 报文的重传,于是拒绝恢复 SYN-ACK。出现这种情况的原因是传输链路上存在 NAT 设备。而缓存 FIN 报文时间戳的TCP Metrics
是Per-Destination
的,在有 NAT 的环境中,服务器看到的 Destination
是 NAT 设备,它看不到 NAT 设备背后还有多大的内部网络,内部网路的每台主机上无法保证 SYN 报文的时间戳递增。
当然,如果和我一样,不能升级内核, 那么不打开 tcp_tw_recycle
也是一个选择
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.