Java八股文——網絡協議


  1. HTTP協議

    • 一次http請求的過程
      • 用戶輸入url,瀏覽器本地解析url,如果在host文件中存有對應ip則訪問對應ip,否則將域名交給DNS服務器,DNS服務器返回對應IP地址,應用層向ip地址發送http請求,然后是傳輸層TCP的三次握手確認連接,第一次是客戶端向服務器發送syn,第二次是服務器發送syn和ack到客戶端,第三次是客戶端發送syn與ack確認,此時TCP握手成功,然后到網絡層,通過ARP協議,使用ip解析出MAC地址,然后通過MAC地址在數據鏈路層傳輸數據,服務器接收到數據包后,由web服務器處理該請求,查找客戶端請求的資源,並返回響應報文。
      • 斷開連接需要TCP4次揮手,任意一方可開始,機器1發送fin=1到機器2表示數據傳輸完畢,斷開請求,機器2返回ack=1確認收到關閉請求,等待機器2的信息傳送完畢后,機器2發送fin=1到機器1,此時機器2會有定時器等待機器1返回ack=1,如果沒有返回,會重發fin=1,機器1返回ack=1確認關閉請求。
    • http與https的區別
      • https需要去CA申請證書
      • http運行在TCP之上,所有傳輸內容都是明文,HTTPS運行在SSL/TLS之上,SSL/TLS運行在TCP之上,所有傳輸內容都是加密的
      • http默認端口80,HTTPS默認端口443
    • GET和POST區別
      • GET方法是從服務器獲取資源
      • POST方法是向指定URI提交數據,數據放在body中
      • GET請求的URL有長度限制,而POST請求數據會放在消息體中,沒有長度限制
      • GET請求會被瀏覽器主動cache,而post不會
      • GET請求在發送過程中產生一個TCP數據包,POST請求會產生兩個數據包。對於GET請求,瀏覽器會將header和data一起發送,服務器返回響應,而POST請求,瀏覽器是先發送header,服務器響應100 continue,瀏覽器再發送data
  2. TCP協議

    1. TCP三次握手與四次揮手,本文第一條
    2. 如何可以繞過三次握手?
      • Linux3.7內核版本之后,提供了TCP Fast Open功能,可以減少TCP連接建立的時延
        1. 客戶端發送 SYN 報文,該報文包含 Fast Open 選項,且該選項的 Cookie 為空,這表明客戶端請求 Fast Open Cookie;
        2. 支持 TCP Fast Open 的服務器生成 Cookie,並將其置於 SYN-ACK 數據包中的 Fast Open 選項以發回客戶端;

        3. 客戶端收到 SYN-ACK 后,本地緩存 Fast Open 選項中的 Cookie。

      • 所以第一次發起請求時,還是需要正常的三次握手,之后如果再次向服務器建立連接的過程:
        1. 客戶端發送 SYN 報文,該報文包含「數據」(對於非 TFO 的普通 TCP 握手過程,SYN 報文中不包含「數據」)以及此前記錄的 Cookie;
        2. 支持 TCP Fast Open 的服務器會對收到 Cookie 進行校驗:如果 Cookie 有效,服務器將在 SYN-ACK 報文中對 SYN 和「數據」進行確認,服務器隨后將「數據」遞送至相應的應用程序;如果 Cookie 無效,服務器將丟棄 SYN 報文中包含的「數據」,且其隨后發出的 SYN-ACK 報文將只確認 SYN 的對應序列號;
        3. 如果服務器接受了 SYN 報文中的「數據」,服務器可在握手完成之前發送「數據」,這就減少了握手帶來的 1 個 RTT 的時間消耗
        4. 客戶端將發送 ACK 確認服務器發回的 SYN 以及「數據」,但如果客戶端在初始的 SYN 報文中發送的「數據」沒有被確認,則客戶端將重新發送「數據」;
        5. 此后的 TCP 連接的數據傳輸過程和非 TFO 的正常情況一致
      • 之后發起 HTTP GET 請求的時候,可以繞過三次握手,這就減少了握手帶來的 1 個 RTT 的時間消耗
      •  /proc/sys/net/ipv4/tcp_fastopen
        • 0 關閉
        • 1 作為客戶端使用 Fast Open 功能
        • 2 作為服務端使用 Fast Open 功能
        • 3 無論作為客戶端還是服務器,都可以使用 Fast Open 功能
    3. UDP與TCP的區別
    4. TCP半連接隊列和全連接隊列
      1. TCP三次握手的時候,Linux內核會維護兩個隊列:
        • 半連接隊列,也稱SYN隊列
        • 全連接隊列,也稱accept隊列
      2. 服務端收到客戶端發起的SYN請求后,內核會把該連接存儲到半連接隊列,並向客戶端返回ACK,服務端收到第三次握手的ACK后,內核會把連接從半連接隊列移除,然后創建新的完全的連接,並將其添加到accept隊列,等待進程調用accept函數時把連接取出來.
      3. 不管是半連接還是全連接隊列,都有最大長度限制,超過限制時,內核會直接丟棄,或返回RST包
      4. 全連接隊列:
        • 查看TCP全連接隊列的大小:服務端使用ss命令
          • ss
            • -l  顯示正在監聽(listening)的socket
            • -n 不解析服務名稱
            • -t  只顯示tcp socket
          • 在LISTEN狀態時(ss -lnt),Recv-Q/Send-Q表示的含義如下:
            • Recv-Q:當前全連接隊列的大小
            • Send-Q:當前全連接最大隊列長度
          • 非LISTEN狀態時(ss -nt)
            • Recv-Q:已收到但未被應用進程讀取的字節數
            • Send-Q:已發送但未收到確認的字節數
        • 當服務端並發處理大量請求時,如果TCP全連接隊列過小,就容易溢出。發生了全連接隊列溢出時,后續的請求就會被丟棄,出現服務端請求數量上不去的現象
        • 丟棄連接是Linux的默認行為,我們可以選擇向客戶端發送RST復位報文,告訴客戶端連接建立失敗。
          /proc/sys/net/ipv4/tcp_abort_on_overflow
          這個文件默認為0
          • 0:表示如果全連接隊列滿了,就扔掉連接
          • 1:表示如果全連接隊列滿了,就發送一個reset包給client,表示廢除握手過程和連接
        • 通常情況下,tcp_abort_on_overflow應該設置為0,更有利於應對突發流量
        • 如何增大TCP全連接隊列?
          • TCP全連接隊列最大值取決於somaxconn和backlog的最小值
            • somaxconn 是 Linux 內核的參數,默認值是 128,可以通過 /proc/sys/net/core/somaxconn 來設置其值;
            • backlog 是 listen(int sockfd, int backlog) 函數中的 backlog 大小,Nginx 默認值是 511,可以通過修改配置文件設置其長度;
            • nginx中backlog設置成5000的demo:
            •  

              設置完后需要重啟 

      5. 半連接隊列:
        • 服務端沒有命令單獨查看半連接隊列,但可以抓住TCP半連接隊列的特點,就是服務端處於SYN_RECV狀態的TCP連接,就是在半連接隊列中
        • 因此,計算TCP半連接隊列長度的命令如下:模擬半連接隊列的溢出場景,實際上就是一直對服務端發送TCP SYN包,但是不回第三次握手的ACK,這樣就會有大量的處於SYN_RECV狀態的TCP連接,其實這就是所謂的SYN洪泛,SYN攻擊,DDos攻擊
          • netstat -natp | grep SYN_RECV | wc -l
        • 半連接隊列的溢出處理是怎么做的?
          • 如果半連接隊列滿了,並且沒有開啟 tcp_syncookies,則會丟棄;
          • 若全連接隊列滿了,且沒有重傳 SYN+ACK 包的連接請求多於 1 個,則會丟棄
          • 如果沒有開啟 tcp_syncookies,並且 max_syn_backlog 減去 當前半連接隊列長度小於 (max_syn_backlog >> 2),則會丟棄;
        • 半連接隊列最大值
          • 當 max_syn_backlog > min(somaxconn, backlog) 時, 半連接隊列最大值 max_qlen_log = min(somaxconn, backlog) * 2;
          • 當 max_syn_backlog < min(somaxconn, backlog) 時, 半連接隊列最大值 max_qlen_log = max_syn_backlog * 2;
        • syncookies
          • 如果 SYN 半連接隊列已滿,開啟 syncookies 功能就可以在不使用 SYN 半連接隊列的情況下成功建立連接
          • syncookies 是這么做的:服務器根據當前狀態計算出一個值,放在己方發出的 SYN+ACK 報文中發出,當客戶端返回 ACK 報文時,取出該值驗證,如果合法,就認為連接建立成功,如下圖所示。
          • syncookies 參數主要有以下三個值:

            • 0 值,表示關閉該功能;

            • 1 值,表示僅當 SYN 半連接隊列放不下時,再啟用它;

            • 2 值,表示無條件開啟功能;

          • 因此,應對SYN攻擊時,只需要設置為1即可
        • 防御SYN攻擊的方法:
          • 增大半連接隊列
            • 通過源碼得知,如果想增大半連接隊列,不能單純增加tcp_max_syn_backlog,還需一同增大somaxconn和backlog,也就是增大全連接隊列,增大tcp_max_syn_backlog和somaxconn的方法就是修改Linux內核參數:路徑分別為:/proc/sys/net/ipv4/tcp_max_syn_backlog
              /proc/sys/net/core/somaxconn
          • 開啟tcp_syncookies功能
            • 路徑為/proc/sys/net/ipv4/tcp_syncookies
          • 減少SYN+ACK重傳次數
            • 當收到SYN攻擊時,就會有大量處於SYN_RECV的TCP連接,服務端此時會重傳SYN+ACK,當重傳次數達到上限后,就會斷開連接,因此,我們可以通過減少SYN+ACK的重傳次數,加快連接斷開來抵御攻擊
            • /proc/sys/net/ipv4/tcp_synack_retries

參考博文:https://mp.weixin.qq.com/s/tRXlq1hErqKQLMMLcxoXvg


免責聲明!

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



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