久久国产精品一区二区三区四区,久色婷婷小香蕉久久,国产日韩欧美在线播放不卡,另类av一区二区

我發現書上寫錯啦!
來源:小林coding    時間:2022-03-01 20:35:21

周末跟朋友討論了一些 TCP 的問題,在查閱《Linux 服務器高性能編程》這本書的時候,發現書上寫了這么一句話:

書上說,處于 TIME_WAIT 狀態的連接,在收到相同四元組的 SYN 后,會回 RST 報文,對方收到后就會斷開連接。

書中作者只是提了這么一句話,沒有給予源碼或者抓包圖的證據。

起初,我看到也覺得這個邏輯也挺符合常理的,但是當我自己去啃了 TCP 源碼后,發現并不是這樣的。

所以,今天就來討論下這個問題,「在 TCP 正常揮手過程中,處于 TIME_WAIT 狀態的連接,收到相同四元組的 SYN 后會發生什么?」

問題現象如下圖,左邊是服務端,右邊是客戶端:

先說結論

在跟大家分析 TCP 源碼前,我先跟大家直接說下結論。

針對這個問題,關鍵是要看 SYN 的「序列號和時間戳」是否合法,因為處于 TIME_WAIT 狀態的連接收到 SYN 后,會判斷 SYN 的「序列號和時間戳」是否合法,然后根據判斷結果的不同做不同的處理。

先跟大家說明下, 什么是「合法」的 SYN?

合法 SYN:客戶端的 SYN 的「序列號」比服務端「期望下一個收到的序列號」要大,并且 SYN 的「時間戳」比服務端「最后收到的報文的時間戳」要大。非法 SYN:客戶端的 SYN 的「序列號」比服務端「期望下一個收到的序列號」要小,或者 SYN 的「時間戳」比服務端「最后收到的報文的時間戳」要小。

上面 SYN 合法判斷是基于雙方都開啟了 TCP 時間戳機制的場景,如果雙方都沒有開啟 TCP 時間戳機制,則 SYN 合法判斷如下:

合法 SYN:客戶端的 SYN 的「序列號」比服務端「期望下一個收到的序列號」要大。非法 SYN:客戶端的 SYN 的「序列號」比服務端「期望下一個收到的序列號」要小。收到合法 SYN

如果處于 TIME_WAIT 狀態的連接收到「合法的 SYN 」后,就會重用此四元組連接,跳過 2MSL 而轉變為 SYN_RECV 狀態,接著就能進行建立連接過程。

用下圖作為例子,雙方都啟用了 TCP 時間戳機制,TSval 是發送報文時的時間戳:

上圖中,在收到第三次揮手的 FIN 報文時,會記錄該報文的 TSval (21),用 ts_recent 變量保存。然后會計算下一次期望收到的序列號,本次例子下一次期望收到的序列號就是 301,用 rcv_nxt 變量保存。

處于 TIME_WAIT 狀態的連接收到 SYN 后,因為 SYN 的 seq(400) 大于 rcv_nxt(301),并且 SYN 的 TSval(30) 大于 ts_recent(21),所以是一個「合法的 SYN」,于是就會重用此四元組連接,跳過 2MSL 而轉變為 SYN_RECV 狀態,接著就能進行建立連接過程。

收到非法的 SYN

如果處于 TIME_WAIT 狀態的連接收到「非法的 SYN 」后,就會再回復一個第四次揮手的 ACK 報文,客戶端收到后,發現并不是自己期望收到確認號(ack num),就回 RST 報文給服務端。

用下圖作為例子,雙方都啟用了 TCP 時間戳機制,TSval 是發送報文時的時間戳:

上圖中,在收到第三次揮手的 FIN 報文時,會記錄該報文的 TSval (21),用 ts_recent 變量保存。然后會計算下一次期望收到的序列號,本次例子下一次期望收到的序列號就是 301,用 rcv_nxt 變量保存。

處于 TIME_WAIT 狀態的連接收到 SYN 后,因為 SYN 的 seq(200) 小于 rcv_nxt(301),所以是一個「非法的 SYN」,就會再回復一個與第四次揮手一樣的 ACK 報文,客戶端收到后,發現并不是自己期望收到確認號,就回 RST 報文給服務端。

客戶端等待一段時間還是沒收到 SYN + ACK 后,就會超時重傳 SYN 報文,重傳次數達到最大值后,就會斷開連接。

PS:這里先埋一個疑問,處于 TIME_WAIT 狀態的連接,收到 RST 會斷開連接嗎?

源碼分析

下面源碼分析是基于 Linux 4.2 版本的內核代碼。

Linux 內核在收到 TCP 報文后,會執行 tcp_v4_rcv 函數,在該函數和 TIME_WAIT 狀態相關的主要代碼如下:

int tcp_v4_rcv(struct sk_buff *skb){ struct sock *sk; ... //收到報文后,會調用此函數,查找對應的 sock sk = __inet_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), th->source, th->dest, sdif, &refcounted); if (!sk) goto no_tcp_socket;process: //如果連接的狀態為 time_wait,會跳轉到 do_time_wait if (sk->sk_state == TCP_TIME_WAIT) goto do_time_wait;...do_time_wait: ... //由tcp_timewait_state_process函數處理在 time_wait 狀態收到的報文 switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { // 如果是TCP_TW_SYN,那么允許此 SYN 重建連接 // 即允許TIM_WAIT狀態躍遷到SYN_RECV case TCP_TW_SYN: { struct sock *sk2 = inet_lookup_listener(....); if (sk2) { .... goto process; } } // 如果是TCP_TW_ACK,那么,返回記憶中的ACK case TCP_TW_ACK: tcp_v4_timewait_ack(sk, skb); break; // 如果是TCP_TW_RST直接發送RESET包 case TCP_TW_RST: tcp_v4_send_reset(sk, skb); inet_twsk_deschedule_put(inet_twsk(sk)); goto discard_it; // 如果是TCP_TW_SUCCESS則直接丟棄此包,不做任何響應 case TCP_TW_SUCCESS:; } goto discard_it;}

該代碼的過程:

接收到報文后,會調用 __inet_lookup_skb() 函數查找對應的 sock 結構;如果連接的狀態是 TIME_WAIT,會跳轉到 do_time_wait 處理;由 tcp_timewait_state_process() 函數來處理收到的報文,處理后根據返回值來做相應的處理。

先跟大家說下,如果收到的 SYN 是合法的,tcp_timewait_state_process() 函數就會返回 TCP_TW_SYN,然后重用此連接。如果收到的 SYN 是非法的,tcp_timewait_state_process() 函數就會返回 TCP_TW_ACK,然后會回上次發過的 ACK。

接下來,看 tcp_timewait_state_process() 函數是如何判斷 SYN 包的。

enum tcp_tw_statustcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, const struct tcphdr *th){ ... //paws_reject 為 false,表示沒有發生時間戳回繞 //paws_reject 為 true,表示發生了時間戳回繞 bool paws_reject = false; tmp_opt.saw_tstamp = 0; //TCP頭中有選項且舊連接開啟了時間戳選項 if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) { //解析選項 tcp_parse_options(twsk_net(tw), skb, &tmp_opt, 0, NULL); if (tmp_opt.saw_tstamp) { ... //檢查收到的報文的時間戳是否發生了時間戳回繞 paws_reject = tcp_paws_reject(&tmp_opt, th->rst); } }.... //是SYN包、沒有RST、沒有ACK、時間戳沒有回繞,并且序列號也沒有回繞, if (th->syn && !th->rst && !th->ack && !paws_reject && (after(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt) || (tmp_opt.saw_tstamp && //新連接開啟了時間戳 (s32)(tcptw->tw_ts_recent - tmp_opt.rcv_tsval) < 0))) { //時間戳沒有回繞 // 初始化序列號 u32 isn = tcptw->tw_snd_nxt + 65535 + 2; if (isn == 0) isn++; TCP_SKB_CB(skb)->tcp_tw_isn = isn; return TCP_TW_SYN; //允許重用TIME_WAIT四元組重新建立連接 } if (!th->rst) { // 如果時間戳回繞,或者報文里包含ack,則將 TIMEWAIT 狀態的持續時間重新延長 if (paws_reject || th->ack) inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN, TCP_TIMEWAIT_LEN); // 返回TCP_TW_ACK, 發送上一次的 ACK return TCP_TW_ACK; } inet_twsk_put(tw); return TCP_TW_SUCCESS;}

如果雙方啟用了 TCP 時間戳機制,就會通過 tcp_paws_reject() 函數來判斷時間戳是否發生了回繞,也就是「當前收到的報文的時間戳」是否大于「上一次收到的報文的時間戳」:

如果大于,就說明沒有發生時間戳繞回,函數返回 false。如果小于,就說明發生了時間戳回繞,函數返回 true。

從源碼可以看到,當收到 SYN 包后,如果該 SYN 包的時間戳沒有發生回繞,也就是時間戳是遞增的,并且 SYN 包的序列號也沒有發生回繞,也就是 SYN 的序列號「大于」下一次期望收到的序列號。就會初始化一個序列號,然后返回 TCP_TW_SYN,接著就重用該連接,也就跳過 2MSL 而轉變為 SYN_RECV 狀態,接著就能進行建立連接過程。

如果雙方都沒有啟用 TCP 時間戳機制,就只需要判斷 SYN 包的序列號有沒有發生回繞,如果 SYN 的序列號大于下一次期望收到的序列號,就可以跳過 2MSL,重用該連接。

如果 SYN 包是非法的,就會返回 TCP_TW_ACK,接著就會發送與上一次一樣的 ACK 給對方。

在 TIME_WAIT 狀態,收到 RST 會斷開連接嗎?

在前面我留了一個疑問,處于 TIME_WAIT 狀態的連接,收到 RST 會斷開連接嗎?

會不會斷開,關鍵看 net.ipv4.tcp_rfc1337 這個內核參數(默認情況是為 0):

如果這個參數設置為 0, 收到 RST 報文會提前結束 TIME_WAIT 狀態,釋放連接。如果這個參數設置為 1, 就會丟掉 RST 報文。

源碼處理如下:

enum tcp_tw_statustcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, const struct tcphdr *th){.... //rst報文的時間戳沒有發生回繞 if (!paws_reject && (TCP_SKB_CB(skb)->seq == tcptw->tw_rcv_nxt && (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq || th->rst))) { //處理rst報文 if (th->rst) { //不開啟這個選項,當收到 RST 時會立即回收tw,但這樣做是有風險的 if (twsk_net(tw)->ipv4.sysctl_tcp_rfc1337 == 0) { kill: //刪除tw定時器,并釋放tw inet_twsk_deschedule_put(tw); return TCP_TW_SUCCESS; } } else { //將 TIMEWAIT 狀態的持續時間重新延長 inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN); } ... return TCP_TW_SUCCESS; }}

TIME_WAIT 狀態收到 RST 報文而釋放連接,這樣等于跳過 2MSL 時間,這么做還是有風險。

sysctl_tcp_rfc1337 這個參數是在 rfc 1337 文檔提出來的,目的是避免因為 TIME_WAIT 狀態收到 RST 報文而跳過 2MSL 的時間,文檔里也給出跳過 2MSL 時間會有什么潛在問題。

TIME_WAIT 狀態之所以要持續 2MSL 時間,主要有兩個目的:

防止歷史連接中的數據,被后面相同四元組的連接錯誤的接收;保證「被動關閉連接」的一方,能被正確的關閉;

雖然 TIME_WAIT 狀態持續的時間是有一點長,顯得很不友好,但是它被設計來就是用來避免發生亂七八糟的事情。

《UNIX網絡編程》一書中卻說道:TIME_WAIT 是我們的朋友,它是有助于我們的,不要試圖避免這個狀態,而是應該弄清楚它。

所以,我個人覺得將 net.ipv4.tcp_rfc1337 設置為 1 會比較安全。

總結

在 TCP 正常揮手過程中,處于 TIME_WAIT 狀態的連接,收到相同四元組的 SYN 后會發生什么?

如果雙方開啟了時間戳機制:

如果客戶端的 SYN 的「序列號」比服務端「期望下一個收到的序列號」要大,并且 SYN 的「時間戳」比服務端「最后收到的報文的時間戳」要大。那么就會重用該四元組連接,跳過 2MSL 而轉變為 SYN_RECV 狀態,接著就能進行建立連接過程。如果客戶端的 SYN 的「序列號」比服務端「期望下一個收到的序列號」要小,或者 SYN 的「時間戳」比服務端「最后收到的報文的時間戳」要小。那么就會再回復一個第四次揮手的 ACK 報文,客戶端收到后,發現并不是自己期望收到確認號,就回 RST 報文給服務端。

在 TIME_WAIT 狀態,收到 RST 會斷開連接嗎?

如果 net.ipv4.tcp_rfc1337 參數為 0,則提前結束 TIME_WAIT 狀態,釋放連接。如果 net.ipv4.tcp_rfc1337 參數為 1,則會丟掉該 RST 報文。

關鍵詞: 斷開連接 持續時間 這個問題

上一篇:

下一篇:

久久国产精品一区二区三区四区,久色婷婷小香蕉久久,国产日韩欧美在线播放不卡,另类av一区二区
亚洲日本在线视频观看| 亚洲深夜福利在线| 激情文学一区| 午夜日韩在线| 久久国产欧美| 国产日韩视频一区二区三区| 在线看不卡av| 欧美大香线蕉线伊人久久国产精品| 99视频超级精品| 亚洲一区二区动漫| 亚洲在线播放电影| 国产精品一区二区在线| 国产精品一区二区三区成人| 久久久女女女女999久久| 亚洲国产三级网| 欧美在线精品免播放器视频| 亚洲国产免费看| 91久久亚洲| 日韩一级裸体免费视频| 亚洲欧洲日本一区二区三区| 国产精品视频精品视频| 欧美在线视频免费观看| 亚洲日本欧美| 欧美精品久久99久久在免费线| 136国产福利精品导航网址| 久久久噜噜噜久久中文字免| 欧美日韩精品一区二区三区| 免费看精品久久片| 久久久水蜜桃av免费网站| 久久伊人一区二区| 欧美日韩精品免费观看视频| 欧美一级二级三级蜜桃| 欧美日韩一区二区在线播放| 亚洲欧美影音先锋| 午夜宅男久久久| 国产精品99久久久久久www| 一区二区国产在线观看| 国产精品成人一区二区| 欧美亚洲在线播放| 欧美日韩国产色视频| 99精品久久久| 欧美区日韩区| 欧美激情乱人伦| 在线综合欧美| 国产综合视频在线观看| 欧美日韩国产片| 久久综合伊人77777| 欧美凹凸一区二区三区视频| 一区二区三区**美女毛片| 亚洲精品日韩欧美| 精品成人国产在线观看男人呻吟| 久久国产精品一区二区| 欧美激情一区二区久久久| 亚洲视频欧美在线| 亚洲激情成人在线| 亚洲国产欧美一区二区三区久久| 亚洲二区精品| 在线日韩欧美视频| 亚洲永久免费视频| 一区二区三区四区国产| 国产精品国产自产拍高清av王其| 欧美日韩国产三级| 国产精品一区二区三区四区| 欧美精品午夜| 久久乐国产精品| 欧美精品久久天天躁| 欧美日韩午夜精品| 国产日韩欧美电影在线观看| 99精品国产高清一区二区| 欧美日本二区| 一区二区三区欧美成人| 一区二区国产在线观看| 午夜亚洲性色福利视频| 亚洲亚洲精品在线观看| 欧美日韩一区二区在线观看视频| 亚洲视频 欧洲视频| 亚洲视频播放| 噜噜噜在线观看免费视频日韩| 亚洲视屏在线播放| 欧美日韩国产二区| 日韩午夜免费视频| 久久久女女女女999久久| 国产欧美日韩视频在线观看| 欧美va亚洲va日韩∨a综合色| 亚洲国产精品成人精品| 国产日产高清欧美一区二区三区| 欧美日韩一区三区四区| 国产一区二区在线观看免费播放| 国产精品盗摄久久久| 亚洲精品影院| 亚洲国产精品久久精品怡红院| 亚洲男人的天堂在线aⅴ视频| 亚洲精选视频免费看| 国产精品高潮呻吟| 亚洲伦理一区| 欧美亚洲日本国产| 国产欧美亚洲日本| 欧美刺激午夜性久久久久久久| 狠狠狠色丁香婷婷综合久久五月| 亚洲另类一区二区| 国产日韩欧美综合一区| 亚洲精品综合久久中文字幕| 久久精品国产综合| 亚洲综合社区| 国产精品国产a级| 极品少妇一区二区| 国产精品99久久久久久有的能看| 欧美日韩网址| 黄色资源网久久资源365| 欧美一级久久| 99xxxx成人网| 国产嫩草一区二区三区在线观看| 国产亚洲午夜| 毛片一区二区| 美脚丝袜一区二区三区在线观看| 国产精品久久久久久久午夜片| 亚洲高清二区| 欧美日韩日本视频| 欧美精品123区| 久久精品综合网| 国产一区二区三区在线观看网站| 好男人免费精品视频| 欧美精品一区二区三区在线播放| 国产伦精品免费视频| 欧美韩日视频| 老司机凹凸av亚洲导航| 欧美日韩妖精视频| 麻豆国产va免费精品高清在线| 国产精品日韩精品| 欧美国产欧美亚州国产日韩mv天天看完整| 在线观看视频免费一区二区三区| 99国产精品私拍| 性欧美8khd高清极品| 中文网丁香综合网| 一区二区三区在线视频免费观看| 一区二区精品在线| 久久综合伊人77777蜜臀| 亚洲狼人综合| 亚洲片区在线| 亚洲精品日本| 亚洲在线国产日韩欧美| 国产女精品视频网站免费| 欧美日韩在线一区| 中文亚洲视频在线| 欧美极品在线观看| 国产自产v一区二区三区c| 国产精品视频午夜| 欧美激情亚洲一区| 在线视频你懂得一区二区三区| 欧美色综合网| 国产区精品在线观看| 99re6热在线精品视频播放速度| 在线成人av网站| 在线视频观看日韩| 国产精品爱啪在线线免费观看| 99视频一区| 国内成人精品视频| 欧美一区二区视频在线观看2020| 亚洲专区在线视频| 亚洲国产精品久久久久婷婷老年| 亚洲欧洲在线一区| 国产日韩一区二区三区| 在线观看一区二区视频| 久久蜜桃香蕉精品一区二区三区| 国产精品亚洲精品| 久久久精品一区| 亚洲欧美日韩中文播放| 欧美日韩一级黄| 欧美日本在线播放| 欧美性色视频在线| 亚洲一区二区在线免费观看视频| 国产精品资源| 亚洲在线国产日韩欧美| 久久一区二区三区超碰国产精品| 久久精品视频免费| 国产日韩精品电影| 国产精品久久久久一区| 欧美一区在线看| 国产一区久久久| 日韩一级欧洲| 亚洲一级一区| 欧美日韩国产欧| 国产精品99久久久久久有的能看| 日韩网站在线看片你懂的| 国产日韩在线亚洲字幕中文| 亚洲直播在线一区| 亚洲特色特黄| 欧美激情视频在线免费观看 欧美视频免费一| 亚洲欧美在线一区二区| 亚洲欧美视频| 国产日韩欧美91| 国产综合精品一区| 亚洲视频电影在线| 麻豆久久久9性大片| 国产精品豆花视频| 亚洲一线二线三线久久久| 美女爽到呻吟久久久久| 欧美国产日韩xxxxx| 亚洲一区三区在线观看| 欧美日本高清一区|