HTTP協議知識總結

更好的瀏覽體驗: http://jie12366.xyz:8081/#/users/11/articles/59

HTTP 1.0

HTTP 1.0的問題

HTTP 1.0中,每一個請求都要開一個連接,請求結束,斷開連接。這樣的協議有兩個問題

  • (1)性能問題:每次請求都打開一個新的連接,因爲連接數有限,而且連接的建立和斷開都很耗時(可能一個頁面就會有幾十個請求)。
  • (2)服務器推送問題:服務器無法主動向客戶端推送消息。

Keep-Alive機制

爲了解決一個請求完成後連接立即斷開的問題,引入了Keep-Alive(保持心跳)機制。客戶端在HTTP請求頭部加上一個字段Connection:Keep-Alive。服務器端收到帶有這樣的字段的請求後,會維護一個Keep-Alive timeout參數,服務器在處理完請求後,不會立即斷開連接,而是會保持連接,如果在timeout時間內都沒有新的請求,那麼服務器纔會關閉這個連接。

HTTP 1.1

連接複用機制

HTTP 1.1將連接複用變成了默認的了,就算不設置字段Connection:Keep-Alive,請求完後也不會立即關閉連接。要想連接不復用,需要設置字段Connection:Close。

Pipeline和Head-of-line Blocking(隊頭阻塞)問題

爲了讓請求變爲併發,引入了Pipeline機制,使得一個請求發出之後,在未收到響應之前,可以立即發送第二個請求。但是這裏有個致命的問題,也就是Head-of-line Blocking(隊頭阻塞)問題。雖然Pipeline機制可以讓請求併發,但是爲了讓請求和響應能配對,響應並不能併發。返回的響應需要按照先進先出的(類似隊列)的順序,所以如果第一個響應由於某些原因,會導致後面的響應會被阻塞。

服務器推送

  1. 客戶端定期輪詢:客戶端每隔一段時間向服務器發送一個請求,如果服務器有消息就返回(效率較低,不建議)。
  2. WebSocket:這是一種基於TCP的可全雙工通信的協議,可實現服務器主動推送。
  3. HTTP長輪詢:保持一個HTTP長連接,如果服務器有新消息,就返回。如果在約定的時間還沒有消息,服務器就返回一個空消息,然後客戶端關閉該連接,再發起一個新的連接。

HTTP/2

由於HTTP 1.1不夠完善,人們就想辦法去提高性能,從而出現了HTTP/2.

與HTTP 1.1兼容

由於HTTP 1.1的應用已成主流,所以想要替代它幾乎不可能,所以只能向它兼容。其實HTTP/2與HTTP1.1並不是平級的,HTTP/2是介於HTTP1.1與TCP之間的一個轉換層。

二進制分幀

爲了解決隊頭阻塞的問題,HTTP/2將一個請求的報文轉換成二進制並分成多個幀來進行傳輸。由於請求和響應都可以亂序的發送,所以需要給每個請求或響應帶上一個ID,好讓他們匹配。二進制分幀其實並沒有完全解決隊頭阻塞的問題,它只是把這個問題轉移到了TCP層面(只要使用TCP協議,爲了保證可靠性,採用先進先出,就一定會有隊頭阻塞的問題)。如果想要徹底解決隊頭阻塞的問題,只能不使用TCP協議,那就是Google提出的QUIC協議。

SSL/TLS

對稱加密的問題

想要傳輸過程中信息加密,那麼採用對稱加密是很安全的。服務器和客戶端都用同一個密鑰對數據進行加密解密。這裏面有個問題就是這個密鑰要怎麼在服務器和客戶端之間傳輸呢?不急,咱先來看看雙向非對稱加密。

雙向非對稱加密

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-i6a05pbf-1576491246600)(https://i.loli.net/2019/12/16/Sy3d8zoXGwYup9T.png)]

如圖所示,客戶端和服務器各自準備一對公鑰密鑰對。客戶端向發送消息時,先用自己的私鑰進行簽名,並用服務器的公鑰來對信息進行加密。服務器收到消息後,用自己的私鑰來對消息解密,並用客戶端的公鑰來驗證簽名(簽名可以證明這個消息是客戶端發送的,且不可抵賴)。服務器向客戶端發送消息也是一樣的過程。
這裏涉及到四個概念,其實就是兩種(簽名和驗籤、加密和解密)。

  • 簽名和驗籤:私鑰簽名,公鑰驗籤,可以防止第三方進行篡改(如果被篡改,驗籤則不能通過),也可以防抵賴(只有私鑰可以簽名)。
  • 加密和解密:公鑰加密,私鑰解密,可以防止第三方竊取信息,即使第三方截取到了傳輸的信息,沒有私鑰,也無法解密。

單向非對稱加密

對於安全性要求特別高的場景,比如個人網銀等,一般都會給用戶一個U盾之類的東西,裏面就是客戶端的公鑰和私鑰,這樣就可以做到雙向非對稱加密。但對於一般的場景,服務器並不需要去驗證客戶端的合法性,只要客戶端驗證服務器的合法性即可。這樣就可以使用單向非對稱+對稱加密來保證傳輸的安全性。這也是SSL的原型。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Uopir2Ch-1576491246603)(https://i.loli.net/2019/12/16/uIpKHSJVTR9xta8.png)]

中間人攻擊

中間人通過僞造服務器的公鑰,然後與客戶端進行通信。造成這個問題的原因是客戶端不能驗證服務器的公鑰的合法性,所以需要數字證書。

數字證書

引入一箇中間機構CA,服務器先把公鑰發給CA,CA給服務器頒發一個數字證書(相當於服務器的身份證),然後服務器將這個證書發給客戶端,客戶端可以驗證這個證書是否是服務器下發的,並可以從證書中獲取服務器的公鑰。數字證書是怎麼驗證的呢?數字證書是通過CA的私鑰簽名生成的,如果被僞造了,那麼CA的公鑰將無法進行驗籤。那麼如果這個CA機構是僞造的呢,那咋辦?

根證書

爲了驗證CA的合法性,所以需要由CA的上一級給CA頒發證書,最頂級的就是根證書了。至於根證書,我們只能無條件信任,它是由世界上公認的一些機構頒發的,並在用戶的操作系統、瀏覽器發佈的時候嵌進去的。如果你信任這個操作系統或瀏覽器,也就信任了這個根證書。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7jb0nsvJ-1576491246604)(https://i.loli.net/2019/12/16/TDoNhpSIOQfGCJm.png)]

可以看一下Google網站的證書,有三級,www.google.com是Google網站自己的證書,它的CA機構是GTS CA 101,它的Root CA是GlobalSign。

SSL/TLS協議

看一下SSL/TLS協議的四次握手。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xLWWfSik-1576491246606)(https://i.loli.net/2019/12/16/ZBrJgDx2shWbQGe.png)]

握手完成後,對稱密鑰的傳輸也完成了。然後客戶端和服務器就可以基於對稱加密來進行加密傳輸了(通過SSL的握手解決了對稱密鑰的傳輸問題)。

HTTPS

HTTPS傳輸過程

HTTPS = HTTP + SSL/TLS。所以HTTPS的傳輸過程如下,先建立TCP連接,在經過SSL/TLS四次握手,就可以進行HTTPS的對稱加密傳輸了。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-WK4RYZVR-1576491246606)(https://i.loli.net/2019/12/16/qgRJHBT2p8x1hAw.png)]

SSL/TLS協議與HTTP/2協議一樣,也是基於TCP和HTTP之間的,所以它兩都是可選的。選了SSL/TLS,那就是HTTPS了。

HTTPS在抓包中明文

這個抓包只限於在本機抓包,如果是第三方抓包(比如黑客),那看到的肯定就是加密的密文了(不然要我HTTPS有何用)。

其實這個抓包軟件就相當於中間人攻擊中的中間人,僞造了一個CA證書(這裏客戶端爲什麼會信任呢,哈哈哈,因爲是用戶自己同意的,用戶自己在計算機安裝了一個抓包軟件自己的根證書,因爲客戶端會無條件信任根證書,那麼抓包軟件僞造了CA證書肯定也會被信任啦。)

抓包軟件截取了客戶端請求,然後向服務器發送這個請求進行握手,獲取到服務器的CA證書,再通過根證書解密獲取到服務器的公鑰,就可以僞造證書啦。抓包軟件利用這個僞造的CA證書獲取了客戶端的信任,並同時冒充客戶端和服務器(這就是中間人)。所以抓包軟件在這裏屬於應用層的,而HTTPS加密是在傳輸層加密(在應用層肯定不加密(除非應用層自己手動加密)啦,因爲是應用層發送的數據),所以在抓包軟件中看到的肯定是明文信息啦。

https的加密沒有安全問題,但它只是用來防止通信過程中被第三方獲取明文(在通信的雙方看到的肯定是明文啦)。如果黑客能直接控制通信的雙方(你的電腦,或服務器),那麼黑客肯定能看到https明文的。

TCP協議

可靠的傳輸

可靠傳輸的三個語義

  • 數據包不丟失。通過ACK確認 + 丟失重發來保證數據包不丟失。
  • 數據包不重複。根據已確認的ACK,將ACK序列之前的數據包直接丟棄,保證不重複。
  • 時序不錯亂。服務器按照數據包的編號來進行ACK確認,如果前面有一個數據包沒收到,後面的不會被確認,直到等待超時重發,後面的數據包也會被全部重發(可用第二種方式去重)。

TCP的連接狀態機

這圖有點複雜,懶得畫了,網上找了一張。
在這裏插入圖片描述

TCP狀態及其描述如下表。

狀態 描述
LISTEN 等待來自遠程TCP應用程序的請求
SYN_SENT 發送連接請求後等待來自遠程端點的確認。TCP第一次握手後客戶端所處的狀態
SYN-RECEIVED 該端點已經接收到連接請求併發送確認。該端點正在等待最終確認。TCP第二次握手後服務端所處的狀態
ESTABLISHED 代表連接已經建立起來了。這是連接數據傳輸階段的正常狀態
FIN_WAIT_1 等待來自遠程TCP的終止連接請求或終止請求的確認
FIN_WAIT_2 在此端點發送終止連接請求後,等待來自遠程TCP的連接終止請求
CLOSE_WAIT 該端點已經收到來自遠程端點的關閉請求,此TCP正在等待本地應用程序的連接終止請求
CLOSING 等待來自遠程TCP的連接終止請求確認
LAST_ACK 等待先前發送到遠程TCP的連接終止請求的確認
TIME_WAIT 等待足夠的時間來確保遠程TCP接收到其連接終止請求的確認

TCP建立連接的三次握手

下圖顯示了TCP三次握手的過程,以及客戶端和服務端狀態的變化
在這裏插入圖片描述
爲什麼需要三次握手呢,因爲前兩次握手只能保證客戶端的發送和接收能力沒問題,但此時服務器只知道自己的接收能力沒問題,需要第三次握手來確認服務器的發送能力也是沒問題的。

TCP斷開連接的四次揮手

下圖顯示了一次典型的TCP四次揮手的過程,以及主動關閉方和被動關閉方的狀態變化。在圖中是客戶端主動斷開了連接,這裏只是舉個例子,服務端一樣可以主動斷開連接。
在這裏插入圖片描述
爲什麼是四次揮手,因爲如果只進行了1、2次。由於TCP是全雙工的,可以處於Half-Close狀態,此時就是處於Half-Close狀態,客戶端到服務器的通道已經關閉,服務器到客戶端的通道還沒關閉,所以需要第三次和第四次來完全關閉連接。

TIME_WAIT狀態

維持TIME_WAIT有兩個原因:

  1. 可靠地實現TCP的全雙工連接終止。
    在四次揮手中,假設最後的ACK丟失了,被動關閉方會重發FIN。主動關閉端必須維護狀態,來允許被動關閉方重發最後的ACK;如果它沒有維護這個狀態,將會對重發FIN返回RST,被動關閉方會認爲這是個錯誤。如果TCP正在執行徹底終止數據流的兩個方向所需的所有工作(即全雙工關閉),則必須正確處理這四個段中任何一個的丟失。所以執行主動關閉的一方必須在結束時保持TIME_WAIT狀態:因爲它可能必須重傳最後的ACK。
  2. 允許舊的重複數據段在網絡中過期
    由於可能會有的數據在網絡中還沒被接收,可能會被新連接給接收,這樣就會造成問題。TCP定義了一個MSL值(默認是120S),也就是一個數據在網絡中停留的最長時間不能超過這個時間。但爲什麼TIME_WAIT的等待時間是MSl * 2呢,因爲第三次可能會發生重傳,而第三次重傳+第四次發送的時間最長是MSL * 2,所以需要讓客戶端在TIME_WAIT狀態等待MSL * 2的時間。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章