<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          我又一次被震驚了。。。

          共 3592字,需瀏覽 8分鐘

           ·

          2021-09-19 07:21

          ?

          ?

          大家好,我是小林。

          昨晚有位讀者問了我這么個(gè)問題:
          大概意思是,一個(gè)已經(jīng)建立的 TCP 連接,客戶端中途宕機(jī)了,而服務(wù)端此時(shí)也沒有數(shù)據(jù)要發(fā)送,一直處于 establish 狀態(tài),客戶端恢復(fù)后,向服務(wù)端建立連接,此時(shí)服務(wù)端會(huì)怎么處理?
          看過我的圖解網(wǎng)絡(luò)的讀者都知道,TCP 連接是由「四元組」唯一確認(rèn)的。
          然后這個(gè)場(chǎng)景中,客戶端的IP、服務(wù)端IP、目的端口并沒有變化,所以這個(gè)問題關(guān)鍵要看客戶端發(fā)送的 SYN 報(bào)文中的源端口是否和上一次連接的源端口相同
          1. 客戶端的 SYN 報(bào)文里的端口號(hào)與歷史連接不相同
          如果客戶端恢復(fù)后發(fā)送的 SYN 報(bào)文中的源端口號(hào)跟上一次連接的源端口號(hào)不一樣,此時(shí)服務(wù)端會(huì)認(rèn)為是新的連接要建立,于是就會(huì)通過三次握手來建立新的連接。
          那舊連接里處于 establish 狀態(tài)的服務(wù)端最后會(huì)怎么樣呢?
          • 如果服務(wù)端發(fā)送了數(shù)據(jù)包給客戶端,由于客戶端的連接已經(jīng)被關(guān)閉了,此時(shí)客戶的內(nèi)核就會(huì)回 RST 報(bào)文,服務(wù)端收到后就會(huì)釋放連接。

          • 如果服務(wù)端一直沒有發(fā)送數(shù)據(jù)包給客戶端,在超過一段時(shí)間后, TCP 保活機(jī)制就會(huì)啟動(dòng),檢測(cè)到客戶端沒有存活后,接著服務(wù)端就會(huì)釋放掉該連接。

          2. 客戶端的 SYN 報(bào)文里的端口號(hào)與歷史連接相同
          如果客戶端恢復(fù)后,發(fā)送的 SYN 報(bào)文中的源端口號(hào)跟上一次連接的源端口號(hào)一樣,也就是處于 establish 狀態(tài)的服務(wù)端收到了這個(gè) SYN 報(bào)文。
          大家覺得服務(wù)端此時(shí)會(huì)做什么處理呢?
          • 丟掉 SYN 報(bào)文?

          • 回復(fù) RST 報(bào)文?

          • 回復(fù) ACK 報(bào)文?

          剛開始我看到這個(gè)問題的時(shí)候,也是沒有思路的,因?yàn)橹皼]關(guān)注過,然后這個(gè)問題不能靠猜,所以我就看了 RFC 規(guī)范和看了 Linux 內(nèi)核源碼,最終知道了答案。
          我不賣關(guān)子,先直接說答案。
          處于 establish 狀態(tài)的服務(wù)端如果收到了客戶端的 SYN 報(bào)文(注意此時(shí)的 SYN 報(bào)文其實(shí)是亂序的,因?yàn)?SYN 報(bào)文的初始化序列號(hào)其實(shí)是一個(gè)隨機(jī)數(shù)),會(huì)回復(fù)一個(gè)攜帶了正確序列號(hào)和確認(rèn)號(hào)的 ACK 報(bào)文,這個(gè) ACK 被稱之為 Challenge ACK
          接著,客戶端收到這個(gè) Challenge ACK,發(fā)現(xiàn)序列號(hào)并不是自己期望收到的,于是就會(huì)回 RST 報(bào)文,服務(wù)端收到后,就會(huì)釋放掉該連接

          RFC 文檔解釋

          rfc793 文檔里的第 34 頁里,有說到這個(gè)例子。
          原文的解釋我也貼出來給大家看看。
          • When the SYN arrives at line 3, TCP B, being in a synchronized state,
            and the incoming segment outside the window, responds with an
            acknowledgment indicating what sequence it next expects to hear (ACK
            100).

          • TCP A sees that this segment does not acknowledge anything it
            sent and, being unsynchronized, sends a reset (RST) because it has
            detected a half-open connection.

          • TCP B aborts at line 5.  

          • TCP A willcontinue to try to establish the connection;

          我就不瞎翻譯了,意思和我在前面用中文說的解釋差不多。

          源碼分析

          處于 establish 狀態(tài)的服務(wù)端如果收到了客戶端的 SYN 報(bào)文時(shí),內(nèi)核會(huì)調(diào)用這些函數(shù):
          tcp_v4_rcv
            -> tcp_v4_do_rcv
              -> tcp_rcv_established
                -> tcp_validate_incoming
                  -> tcp_send_ack
          我們只關(guān)注 tcp_validate_incoming 函數(shù)是怎么處理 SYN 報(bào)文的,精簡(jiǎn)后的代碼如下:
          從上面的代碼實(shí)現(xiàn)可以看到,處于 establish 狀態(tài)的服務(wù)端,在收到報(bào)文后,首先會(huì)判斷序列號(hào)是否在窗口內(nèi),如果不在,則看看 RST 標(biāo)記有沒有被設(shè)置,如果有就會(huì)丟掉。然后如果沒有 RST 標(biāo)志,就會(huì)判斷是否有 SYN 標(biāo)記,如果有 SYN 標(biāo)記就會(huì)跳轉(zhuǎn)到 syn_challenge 標(biāo)簽,然后執(zhí)行 tcp_send_challenge_ack 函數(shù)。
          tcp_send_challenge_ack 函數(shù)里就會(huì)調(diào)用 tcp_send_ack 函數(shù)來回復(fù)一個(gè)攜帶了正確序列號(hào)和確認(rèn)號(hào)的 ACK 報(bào)文。

          如何關(guān)閉一個(gè) TCP 連接?

          我這里問題大家這么一個(gè)問題,如何一個(gè) TCP 連接?
          可能大家第一反應(yīng)是「殺掉進(jìn)程」不就行了嗎?
          是的,這個(gè)是最粗暴的方式,殺掉客戶端進(jìn)程和服務(wù)端進(jìn)程影響的范圍會(huì)有所不同:
          • 在客戶端殺掉進(jìn)程的話,就會(huì)發(fā)送 FIN 報(bào)文,來斷開這個(gè)客戶端進(jìn)程與服務(wù)端建立的所有 TCP 連接,這種方式影響范圍只有這個(gè)客戶端進(jìn)程所建立的連接,而其他客戶端或進(jìn)程不會(huì)受影響。

          • 而在服務(wù)端殺掉進(jìn)程影響就大了,此時(shí)所有的 TCP 連接都會(huì)被關(guān)閉,服務(wù)端無法繼續(xù)提供訪問服務(wù)。

          所以,關(guān)閉進(jìn)程的方式并不可取,最好的方式要精細(xì)到關(guān)閉某一條 TCP 連接。
          有的小伙伴可能會(huì)說,偽造一個(gè)四元組相同的 RST 報(bào)文不就行了?
          這個(gè)思路很好,但是不要忘了還有個(gè)序列號(hào)的問題,你偽造的 RST 報(bào)文的序列號(hào)一定能被對(duì)方接受嗎?
          如果 RST 報(bào)文的序列號(hào)不能落在對(duì)方的滑動(dòng)窗口內(nèi),這個(gè) RST 報(bào)文會(huì)被對(duì)方丟棄的,就達(dá)不到關(guān)閉的連接的效果。
          所以,要偽造一個(gè)能關(guān)閉 TCP 連接的 RST 報(bào)文,必須同時(shí)滿足「四元組相同」和「序列號(hào)正好落在對(duì)方的滑動(dòng)窗口內(nèi)」這兩個(gè)條件
          直接偽造符合預(yù)期的序列號(hào)是比較困難,因?yàn)槿绻粋€(gè)正在傳輸數(shù)據(jù)的 TCP 連接,滑動(dòng)窗口時(shí)刻都在變化,因此很難剛好偽造一個(gè)剛好落在對(duì)方滑動(dòng)窗口內(nèi)的序列號(hào)的 RST 報(bào)文。
          辦法還是有的,我們可以偽造一個(gè)四元組相同的 SYN 報(bào)文,來拿到“合法”的序列號(hào)!
          正如我們最開始學(xué)到的,如果處于 establish 狀態(tài)的服務(wù)端,收到四元組相同的 SYN 報(bào)文后,會(huì)回復(fù)一個(gè) Challenge ACK,這個(gè) ACK 報(bào)文里的「確認(rèn)號(hào)」,正好是服務(wù)端下一次想要接收的序列號(hào),說白了,就是可以通過這一步拿到服務(wù)端下一次預(yù)期接收的序列號(hào)。
          然后用這個(gè)確認(rèn)號(hào)作為 RST 報(bào)文的序列號(hào),發(fā)送給服務(wù)端,此時(shí)服務(wù)端會(huì)認(rèn)為這個(gè) RST 報(bào)文里的序列號(hào)是合法的,于是就會(huì)釋放連接!
          在 Linux 上有個(gè)叫 killcx 的工具,就是基于上面這樣的方式實(shí)現(xiàn)的,它會(huì)主動(dòng)發(fā)送 SYN 包獲取 SEQ/ACK 號(hào),然后利用 SEQ/ACK 號(hào)偽造兩個(gè) RST 報(bào)文分別發(fā)給客戶端和服務(wù)端,這樣雙方的 TCP 連接都會(huì)被釋放,這種方式活躍和非活躍的 TCP 連接都可以殺掉。
          使用方式也很簡(jiǎn)單,只需指明客戶端的 IP 和端口號(hào)。
          ./killcx <IP地址>:<端口號(hào)>
          killcx 工具的工作原理,如下圖。
          它偽造客戶端發(fā)送 SYN 報(bào)文,服務(wù)端收到后就會(huì)回復(fù)一個(gè)攜帶了正確「序列號(hào)和確認(rèn)號(hào)」的 ACK 報(bào)文(Challenge ACK),然后就可以利用這個(gè) ACK 報(bào)文里面的信息,偽造兩個(gè) RST 報(bào)文
          • 用 Challenge ACK 里的確認(rèn)號(hào)偽造 RST 報(bào)文發(fā)送給服務(wù)端,服務(wù)端收到 RST 報(bào)文后就會(huì)釋放連接。

          • 用 Challenge ACK 里的序列號(hào)偽造 RST 報(bào)文發(fā)送給客戶端,客戶端收到 RST 也會(huì)釋放連接。

          正是通過這樣的方式,成功將一個(gè) TCP 連接關(guān)閉了!
          這里給大家貼一個(gè)使用 killcx 工具關(guān)閉連接的抓包圖,大家多看看序列號(hào)和確認(rèn)號(hào)的變化。
          所以,以后抓包中,如果莫名奇妙出現(xiàn)一個(gè) SYN 包,有可能對(duì)方接下來想要對(duì)你發(fā)起的 RST 攻擊,直接將你的 TCP 連接斷開!
          怎么樣,很巧妙吧!
          當(dāng)時(shí)我了解到這種方式關(guān)閉 TCP 連接的時(shí)候,我也是相當(dāng)震驚的(末尾點(diǎn)題,手動(dòng)狗頭)。
          ?

          ?

          瀏覽 91
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天爽天天澡天天爽精品视频 | 欧美性爱网址大全 | 日本精品在线视频 | 18岁毛片| 综合伊人 |