問題症狀:
Linux伺服器收到SYN請求報文後,不響應ACK,導致客戶端建立TCP連線失敗。
您可以通過netstat命令檢視系統協議統計資訊,發現很多請求因時間戳而被拒絕
通過幫助找出有相同的人遇到此問題:
是通過調整 sysctl -w netipv4.tcp tw recycle=0 來解決這個問題。
發現該問題是由 Linux TCP TW 回收 TCP 時間戳設定引起的。 如果在Linux核心原始碼中開啟了TCP TW回收TCP時間戳,則同一源IP主機的套接字連線請求中的時間戳必須在60秒內遞增。
我這邊和其他同事通過公司的出口訪問問題伺服器(NAT閘道器只有1個IP位址),因為時間戳時間是從系統開機到當前時間,所以我和其他同事的時間戳肯定是不一樣的; 根據 SYN 報文的原始碼,當同時啟用 TCP TW Recycle 和 TCP TimeStamp 時,Timestamp 較大的主機成功訪問 servern,而 TimeStamp 較小的主機無法訪問 servern。
已解決:回聲"0" > /proc/sys/net/ipv4/tcp_tw_recycle
理論補充:1.淨ipv4.tcp_timestamps
TCP時間戳的本質是記錄資料包的傳送時間。 基本步驟如下:
當傳送方傳送資料時,它會在資料包中放置乙個時間戳(指示傳送時間)。
接收方收到報文後,將接收到的時間戳返回給對應ACK報文的傳送方
收發ACK報文後,可以使用NOW - ACK報文中的時間戳獲取準確的RTT
時間戳是乙個雙向選項,當一方未啟用時,它會停用雙方。 例如,客戶端傳送的 SYN 資料包包含 timestamp 選項,但伺服器未啟用此選項。 回覆的 syn-ack 沒有 timestamp 選項,客戶端後續回覆的 ACK 沒有 timestamp 選項。 當然,如果客戶端傳送的 SYN 資料包不包含時間戳,則時間戳將在兩個方向上被禁用。
TCP 資料包中 Timestamp 的值是從系統啟動時間到當前時間的(毫秒級)時間戳。
引數:0:已停用。
1:啟用(系統預設值)。
2、net.ipv4.tcp_tw_recycle
處於 TCP 規範中指定的時間等待中的 TCP 連線必須等待 2 MSL 時間。 但是,在 Linux 中,如果啟用了 TCP TW 回收,則 Time Wait 的 TCP 連線不會等待 2MSL 時間(RTO 或 60S),從而實現快速復用(**處於 Time Wait 狀態的 TCP 連線)。 這可能會導致連線從以前的連線接收資料。 為此,Linux 會在啟用 TCP TW 回收時記錄時間等待連線的對等資訊,包括 IP 位址和時間戳。 這樣,當核心收到相同IP的SYN報文時,會比較時間戳,檢查SYN報文的時間戳是否滯後,如果滯後,就會扔掉(以為是舊連線的資料)。 這在大多數情況下是可以的,但是對於我們實際的客戶端-伺服器服務,訪問我們服務的使用者一般位於NAT之後,如果多個使用者在NAT之後訪問同一服務,則可能會因時間戳滯後而丟失連線。
引數:0:禁用(系統預設值)。
1:已啟用。 預設值:
使用預設值確定
檢視核心引數。
方法一:使用“proc sys”目錄,通過cat命令檢視對應檔案的內容。 “proc sys”目錄是Linux核心啟動後生成的偽目錄,目錄下的net資料夾存放了當前系統中所有有效的核心引數,目錄樹結構與引數的全稱相關,如netipv4.TCP TW Recycle,對應 proc sys net IPv4 TCP TW recycle,檔案內容為引數值。 cat /proc/sys/net/ipv4/tcp_tw_recycle
方法二:通過“etc sysctl”。conf“檔案。 執行以下命令,檢視當前系統中生效的所有引數。 /usr/sbin/sysctl -a
修改核心引數。
方法一:使用proc sys目錄下的echo命令修改核心引數對應的檔案。 該方法修改後的引數值僅在當前執行中生效,重啟後會重置為原始引數值,一般用於臨時校驗。 要永久生效,請參閱方法 2。 echo "0" > /proc/sys/net/ipv4/tcp_tw_recycle。
方法二:通過“etc sysctl”。conf“檔案。 該方法修改後的引數值永久生效。 (建議第二個選項)。