問題描述:
最近更換升級了服務器后,一直有個問題,就是很多用戶能ping通和tracert通我們的網站,但登陸的時候不正常,偶爾刷新能打開,很不正常。
抓包發現,用戶過來的IP能到服務器,但服務器沒有回復。
感謝黃總的分析!!!!
以下是從網上找的一些解決方法總結。
============================================================================================================================
原文:http://blog.csdn.net/gzh0222/article/details/8000508
針對有些用戶能ping通我們的網站,但是連接時超時服務器沒有任何響應,懷疑問題處在了了http的三次握手環節,這是決定通過抓包進行分析:
1、有問題機器的截圖:
2、正常機器的截圖:
3、發現問題
從抓包數據發現,web服務器對出問題機器和正常機器系統的tcp syn包都返回ACK包,但存在問題發出的tcp syn包有時候響應,有時候不響應。不響應時,終端與web服務器之間的tcp連接無法正常建立,導致頁面不能打開。對比這兩種數據包,就在時間戳上有差異,存在問題的機器發出的tcp syn包帶有時間戳,因此懷疑時間戳問題導致的故障。
4、解決問題
既然懷疑是時間戳導致的,那我們就着手分析如果將出現問題的機器的時間戳去掉會不會解決問題。針對帶有時間戳的tcp syn包不響應的問題,查閱了相關資料得知產生問題的原因是出問題系統中的注冊表中有Tcp1323opts這個選項,會導致其在發包時加入時間戳,經過nat之后,如果前面相同的端口被使用過,且時間戳大於這個鏈接發出的syn中的時間戳,服務器上就會忽略掉這個syn,不返會syn-ack消息,表現為用戶無法正常完成tcp3次握手,從而不能打開web頁面。在業務閑時,如果用戶nat的端口沒有被使用過時,就可以正常打開;業務忙時,nat端口重復使用的頻率高,很難分到沒有被使用的端口,從而產生這種問題。
目前看有兩種方法解決:
(1) 是在服務器上修改變量
首先我們先查看一下我們服務器net.ipv4.tcp_timestamps的默認值,如果該值為0測說名不是該問題導致,如果是1我們需要將該值設置為1。
查看默認值的方法:[root@localhost ~]# cat /proc/sys/net/ipv4/tcp_timestamps
修改該值的方法:vim /etc/sysctl.conf 添加 net.ipv4.tcp_timestamps=0
(2)修改客戶端的注冊表Tcp1323Opts設置為0。
備注:
Tcp1323Opts
說明:該參數控制 RFC 1323 時間戳與窗口縮放選項。默認情況下,啟用時間戳與
窗口縮放,但是可以使用標志位進行控制。0 位控制窗口縮放,1 位控制時間戳。
值為0(禁用 RFC 1323 選項)
值為1(僅啟用窗口縮放)
值為2(僅啟用時間戳)
值為3(兩個選項均啟用)
net.ipv4.tcp_timestamps=0
說明:時間戳可以避免序列號的卷繞。一個1Gbps的鏈路肯定會遇到以前用過的序列號。時間戳能夠讓內核接受這種“異常”的數據包。這里需要將其關掉。
值為0(禁用時間戳)
值為1(啟用時間戳)
只有客戶端和服務端都開啟時間戳的情況下,才會出現能ping通不能建立tcp三次握手的情況,所以做為提供服務的公司,不可能保證所有的用戶都關閉時間戳,這個功能,所以我們必須關閉時間戳,這樣才能給所用用戶提供正常的服務。
使用該命令使其立馬生效:/sbin/sysctl-p
============================================================================================================================
原文:http://blog.sina.com.cn/s/blog_781b0c850100znjd.html
近來線上陸續出現了一些connect失敗的問題,經過分析試驗,最終確認和proc參數tcp_tw_recycle/tcp_timestamps相關;
1. 現象
第一個現象:模塊A通過NAT網關訪問服務S成功,而模塊B通過NAT網關訪問服務S經常性出現connect失敗,抓包發現:服務S端已經收到了syn包,但沒有回復synack;另外,模塊A關閉了tcp timestamp,而模塊B開啟了tcp timestamp;
第二個現象:不同主機上的模塊C(開啟timestamp),通過NAT網關(1個出口ip)訪問同一服務S,主機C1 connect成功,而主機C2 connect失敗;
2. 分析
根據現象上述問題明顯和tcp timestmap有關;查看linux 2.6.32內核源碼,發現tcp_tw_recycle/tcp_timestamps都開啟的條件下,60s內同一源ip主機的socket connect請求中的timestamp必須是遞增的。
源碼函數:tcp_v4_conn_request(),該函數是tcp層三次握手syn包的處理函數(服務端);
源碼片段:
if (tmp_opt.saw_tstamp &&
tcp_death_row.sysctl_tw_recycle &&
(dst = inet_csk_route_req(sk, req)) != NULL &&
(peer = rt_get_peer((struct rtable *)dst)) != NULL &&
peer->v4daddr == saddr) {
if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
(s32)(peer->tcp_ts - req->ts_recent) >
TCP_PAWS_WINDOW) {
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
goto drop_and_release;
}
}
tmp_opt.saw_tstamp:該socket支持tcp_timestamp
sysctl_tw_recycle:本機系統開啟tcp_tw_recycle選項
TCP_PAWS_MSL:60s,該條件判斷表示該源ip的上次tcp通訊發生在60s內
TCP_PAWS_WINDOW:1,該條件判斷表示該源ip的上次tcp通訊的timestamp 大於 本次tcp
分析:主機client1和client2通過NAT網關(1個ip地址)訪問serverN,由於timestamp時間為系統啟動到當前的時間,因此,client1和client2的timestamp不相同;根據上述syn包處理源碼,在tcp_tw_recycle和tcp_timestamps同時開啟的條件下,timestamp大的主機訪問serverN成功,而timestmap小的主機訪問失敗;
參數:/proc/sys/net/ipv4/tcp_timestamps - 控制timestamp選項開啟/關閉
/proc/sys/net/ipv4/tcp_tw_recycle - 減少timewait socket釋放的超時時間
3. 解決方法
echo 0 > /proc/sys/net/ipv4/tcp_tw_recycle;
tcp_tw_recycle默認是關閉的,有不少服務器,為了提高性能,開啟了該選項;
為了解決上述問題,個人建議關閉tcp_tw_recycle選項,而不是timestamp;因為 在tcp timestamp關閉的條件下,開啟tcp_tw_recycle是不起作用的;而tcp timestamp可以獨立開啟並起作用。
源碼函數: tcp_time_wait()
源碼片段:
if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp)
recycle_ok = icsk->icsk_af_ops->remember_stamp(sk);
......
if (timeo < rto)
timeo = rto;
if (recycle_ok) {
tw->tw_timeout = rto;
} else {
tw->tw_timeout = TCP_TIMEWAIT_LEN;
if (state == TCP_TIME_WAIT)
timeo = TCP_TIMEWAIT_LEN;
}
inet_twsk_schedule(tw, &tcp_death_row, timeo,
TCP_TIMEWAIT_LEN);
timestamp和tw_recycle同時開啟的條件下,timewait狀態socket釋放的超時時間和rto相關;否則,超時時間為TCP_TIMEWAIT_LEN,即60s;
內核說明文檔 對該參數的介紹如下:
tcp_tw_recycle - BOOLEAN
Enable fast recycling TIME-WAIT sockets. Default value is 0.
It should not be changed without advice/request of technical
experts.
原文鏈接:http://blog.sina.com.cn/u/2015038597
============================================================================================================================
原文:http://www.verydemo.com/demo_c167_i3289.html
linux 服務器 無法建立TCP連接 時間戳 net.ipv4.tcp_timestamps
一.情況表現為
1.在公司內網對站點的http訪問:
linux主機出現故障:curl以及抓包分析,發現服務端不響應linux客戶端的請求,無法建立TCP連接,瀏覽器返回“無法連接到服務器”
windows主機正常
2.http訪問質量下降:
基調顯示,新架構上線后,訪問質量下滑,主要表現為
2.1.訪問提示“無法連接到服務器”
2.2.僅少數人遇到這種故障,並且一天中不是每次訪問都會遇到,而是出現時好時壞的現象
二.處理過程
直接上google搜索關鍵字“服務器無法建立TCP連接”。
翻了幾頁后,發現這篇博文:“http://www.sunchis.com/html/os/linux/2012/0518/413.html”。
看了一下,和我們公司內網的表現一模一樣,但各種問題(1為這方面基礎知識薄弱,2為沒有時間驗證此配置)
然后這種問題持續了n久...一直以為是內部設備問題
后期搞不定了,大膽在線上啟用這個參數“net.ipv4.tcp_timestamps = 0”,做了下測試后,發現故障解除,原故障機每次訪問都正常了!
不過還是不明其中原理,只是大意了解,同樣處於NAT上網方式的用戶里(與別人共用出口IP地址),如果你的時間戳小於別人的,那么服務器不會響應你的TCP請求,要忽略此項,將net.ipv4.tcp_timestamps = 0(/etc/sysctl.conf)
三.總結
后期學習時,看見了一個更加詳細的博客,講的很詳細,也引入了新的問題:http://huoding.com/2012/01/19/142
====== 小抄 ======
其實,linux服務器原本對時間戳(timestamps)默認是不開啟的,Linux是否啟用這種行為取決於tcp_timestamps和tcp_tw_recycle,因為tcp_timestamps缺省就是開啟的,所以當tcp_tw_recycle被開啟后,實際上這種行為就被激活了。
net.ipv4.tcp_tw_recycle又是啥呢,搜索了一下基本上是TIME_WAIT連接的回收參數
當 net.ipv4.tcp_timestamps 沒有設置(缺省為開啟),並且 net.ipv4.tcp_tw_recycle 也開啟時,這個坑爹的錯誤就出現了,但是注意,只表現在NAT網絡環境中。而且,大多數博客,以及一些大牛們,都有說過要開啟 net.ipv4.tcp_tw_recycle ...
====== 小抄 ======
四.未完成的事項
上文 http://huoding.com/2012/01/19/142 中提到的:
1.(未驗證)關閉timestamps后,tw_recycle功能是失效的問題
2.(未驗證)新的解決TIME_WAIT連接過多的方法:net.ipv4.tcp_max_tw_buckets = 10000 設置一個最大值,不過壞處是系統日志會提示:TCP: time wait bucket table overflow