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.