程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> TCP服務端收到syn但是不回復syn ack問題分析

TCP服務端收到syn但是不回復syn ack問題分析

編輯:關於PHP編程

TCP服務端收到syn但是不回復syn ack問題分析


TCP服務端收到syn但是不回復syn ack問題分析
——lvyilong316

最近在分析客戶的一個問題時遇到了一種奇怪的情況,客戶在服務端開啟了某個端口,但是在客戶端telnet確一直不通。通過在服務端抓包發現,客戶端的syn分節已經到達,但是服務端並沒有應答。查看了一下當前連接數,發現連接數也不大,所以排除是連接隊列滿造成的。後來忽然想起了net.ipv4.tcp_tw_recycle選項可能引起這個問題,於是關閉了這個選項,問題果然得以解決。這裡分析一下原因。

有些服務器(當然客戶端也可以)為了避免TIME_WAIT狀態占用連接,希望能加快TIME_WAIT狀態的回收,通常將net.ipv4.tcp_tw_recycle選項開啟。當然這個選項的生效要依賴net.ipv4.tcp_timestamps選項的開啟。雖然開啟這個選項能夠加快TIME_WAIT連接的回收,但卻引入了另一個問題。我們先看下tcp_tw_recycle選項的工作機制:

當開啟了tcp_tw_recycle選項後,當連接進入TIME_WAIT狀態後,會記錄對應遠端主機最後到達分節的時間戳。如果同樣的主機有新的分節到達,且時間戳小於之前記錄的時間戳,即視為無效,相應的數據包會被丟棄(rfc1323)。

Linux是否啟用這種行為取決於tcp_timestamps和tcp_tw_recycle,因為tcp_timestamps缺省就是開啟的,所以當tcp_tw_recycle被開啟後,實際上這種行為就被激活了。

現在很多公司都用LVS做負載均衡,通常是前面一台LVS,後面多台後端服務器,這其實就是NAT,當請求到達LVS後,它修改地址數據後便轉發給後端服務器,但不會修改時間戳數據,對於後端服務器來說,請求的源地址就是LVS的地址,加上端口會復用,所以從後端服務器的角度看,原本不同客戶端的請求經過LVS的轉發,就可能會被認為是同一個連接,加之不同客戶端的時間可能不一致,所以就會出現時間戳錯亂的現象,於是後面的數據包就被丟棄了,具體的表現通常是是客戶端明明發送的SYN,但服務端就是不響應ACK,還可以通過下面命令來確認數據包不斷被丟棄的現象:

shell> netstat -s | grep timestamp

... packets rejects in established connections because of timestamp

如果服務器身處NAT環境,安全起見,通常要禁止tcp_tw_recycle,至於TIME_WAIT連接過多的問題,可以通過激活tcp_tw_reuse來緩解(只對客戶端有作用)。

當然關閉tcp_timestamps選項也是可以避免這個問題的:

設置sysctl.conf裡面tcp_timestamps=0也可以只用命令sysctl -w net.ipv4.tcp_timestamps=0

但個人建議關閉tcp_tw_recycle選項,而不是timestamp;因為 在tcp timestamp關閉的條件下,開啟tcp_tw_recycle是不起作用的;而tcp timestamp可以獨立開啟並起作用。此外tcp timestamp還和其他選項起作用有關,如tcp_tw_reuse。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved