服務端tcp syn無響應,無回復


說一下現象是用tpcping 域名 443端口會時斷時續的,還很有規律,web頁面登錄狀態也會不斷的失效,通過客戶端,網關出口,clb,后端 rs抓包查看發現,客戶端到clb都正常,clb把tcp syn請求轉發給后端rs, rs沒有回應

通過查閱資料,發現tcp_timestamps默認是開啟,如果再把tcp_tw_recycle設置為1,則60s內同一源ip主機的socket connect請求中的timestamp必須是遞增的。
也就是說服務器打開了 tcp_tw_reccycle了,就會檢查時間戳,如果對方發來的包的時間戳是亂跳的或者說時間戳是滯后的,這樣服務器肯定不會回復,
所以服務器就把帶了“倒退”的時間戳的包當作是“recycle的tw連接的重傳數據,不是新的請求”,於是丟掉不回包,就出現了開始說的syn不響應。 經過nat之后,如果前面相同的端口被使用過,且時間戳大於這個鏈接發出的syn中的時間戳,服務器上就會忽略掉這個syn,不返會syn
-ack消息,表現為用戶無法正常完成tcp3次握手,
從而不能打開web頁面。在業務閑時,如果用戶nat的端口沒有被使用過時,就可以正常打開;業務忙時,nat端口重復使用的頻率高,很難分到沒有被使用的端口,從而產生這種問題。 只有客戶端和服務端都開啟時間戳的情況下,才會出現能ping通不能建立tcp三次握手的情況 netstat
-s | grep timestamp

在nat環境下,因為tcp_tw_recycle=1和net.ipv4.tcp_timestamps=1引起 Nginx upstream timed out 

故障情況:

阿里雲賬號A的A機房,內網里面部署兩台Nginx,通過網絡出口(NAT),代理用戶訪問到阿里雲賬號B的B機房服務。A機房的Nginx出現:upstream timed out 。

故障的誘因是:net.ipv4.tcp_timestamps=1

2015的捉包圖為:

直接上當年的筆記:

先看看TCP IP 對tw的一些解析:
RFC 1323里有這樣的定義:
An additional mechanism could be added to the TCP, a per-host
cache of the last timestamp received from any connection.
This value could then be used in the PAWS mechanism to reject
old duplicate segments from earlier incarnations of the
connection, if the timestamp clock can be guaranteed to have
ticked at least once since the old connection was open. This
would require that the TIME-WAIT delay plus the RTT together
must be at least one tick of the sender's timestamp clock.
Such an extension is not part of the proposal of this RFC.
大概的中文意思就是:TCP協議中有一種機制,緩存了每個主機(即ip)過來的連接最新的timestamp值。這個緩存的值可以用於PAWS(Protect Against Wrapped Sequence numbers,是一個簡單的防止重復報文的機制)中,來丟棄當前連接中可能的舊的重復報文。而Linux實現這個機制的方法就是同時啟用net.ipv4.tcp_timestamps和net.ipv4.tcp_tw_recycle 這兩個選項。
這種機制在 客戶端-服務器 一對一的時候,沒有任何問題,但是當服務器在負載均衡器后面時,由於負載均衡器不會修改包內部的timestamp值,而互聯網上的機器又不可能保持時間的一致性,再加上負載均衡是會重復多次使用同一個tcp端口向內部服務器發起連接的,就會導致什么情況呢:

負載均衡通過某個端口向內部的某台服務器發起連接,源地址為負載均衡的內部地址——同一假如恰巧先后兩次連接源端口相同,這台服務器先后收到兩個包,第一個包的timestamp被服務器保存着,第二個包又來了,一對比,發現第二個包的timestamp比第一個還老——客戶端時間不一致。服務器基於PAWS,判斷第二個包是重復報文,丟棄之。

反映出來的情況就是在服務器上抓包,發現有SYN包,但服務器就是不回ACK包,因為SYN包已經被丟棄了。為了驗證這一結果,可以執行netstat -s | grep timestamp 命令,看輸出里面passive connections rejected by timestamp 一項的數字變化。

解決辦法:

tcp_tw_recycle=0 或(和)net.ipv4.tcp_timestamps=0

查看配置
cat /proc/sys/net//ipv4/tcp_timestamps
cat /proc/sys/net//ipv4/tcp_tw_recycle

修改配置
sysctl -w net.ipv4.tcp_timestamps=0
sysctl -w net.ipv4.tcp_tw_recycle=0

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM