天天看點

萬字長文拿下HTTP

本文将從以下幾個方面進行分享。其中包括HTTP發展史,HTTP緩存代理機制,常用的web攻擊,HTTP和HTTPS的流量識别,網絡協定學習的工具推薦以及高頻HTTP與HTTPS的高頻面試題題解等,開工。

提綱

1989年,蒂姆·伯納斯 - 李(Tim Berners-Lee)在論文中提出可以在網際網路上建構超連結文檔,并提出了三點.

URI:統一資源辨別符。網際網路的唯一ID

HTML:超文本文檔

HTTP:傳輸超文本的文本傳輸協定

1 HTTP應用在哪兒

學習一門知識,采用五分鐘時間看看這個知識是幹啥的可能會更加有目的性。HTTP可謂無處不在,這裡例舉出幾個。

HTTP應用場景

2 HTTP是什麼

HTTP(hypertext transport protocol)翻譯過來為"超文本傳輸協定",文本可以了解為簡單的字元文字組合,也可以了解為更為複雜的音頻或者圖像等。那麼将這個詞語拆分為三個部分。

超文本傳輸協定

"超文本"和"文本"相比多了一個字"超",這樣看來比文本豐富,因為它可以将多種文本/圖像等進行混合,更重要的是可以從一個文本跳轉到另一個文本(文本連接配接)。

"傳輸",傳輸的過程中需要溝通,溝通即可能一對一溝通也可能一對多溝通(進行内容協商),無論怎麼樣,參加溝通的人數>1,想盡一切一切辦法更快更好的完成相應的任務。

"協定",無規矩不成方圓,做機密項目之前需要簽署保密協定,找工作要簽"三方協定",三方協定是學校,公司,和個人組成的協定,都是為了讓大家受一定的限制,違反了即有相應的懲罰。

三方協定

3 不同版本的HTTP

HTTP/0.9

當時網絡資源匮乏,0.9版本相對簡單,采用純文字格式,且設定為隻讀,是以當時隻能使用"Get"的方式從伺服器獲的HTML文檔,響應以後則關閉。如下圖所示

GET /Mysite.html           

響應中隻包含了文檔本身。響應内容無響應頭,無錯誤碼,無狀态碼,可以說是"裸奔"。

<HTML>
Hello world
</HTML>
HTTP/1.0           

此時HTTP/0.9請求過程如下

  • 應用層的HTTP建立在傳輸層的TCP之上并運用TCP可靠性等特性,先三次握手建立連接配接
  • 用戶端請求建立連接配接(此時隻有GET)
  • 服務端響應請求,資料以 ASCII 字元流傳回給客戶端
  • 傳輸完成,斷開連接配接。

HTTP 0.9

HTTP1.0

随着時代的進步,僅僅文本的傳輸無法滿足需求,更多情況需要采用圖文的方式才能生動的表達出自己的觀點。随着1995年開發出Apache,同時其它的多媒體等技術發展迅速,進而進一步的促使HTTP新功能的出現。HTTP1.0在1996年誕生,增加了一下幾個方面:

  • 之前隻有Get方法,現在增加Post(加參數),Head方法
  • 加入協定版本号,同時添加檔案處理類型
  • 加入HTTP Header,讓HTTP處理請求更加靈活
  • 增加響應狀态碼,标記出錯的原因
  • 提供國際化(不同語言)支援

典型的請求過程

GET /image.html HTTP/1.0
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64)

200 OK
Date: Tue, 17 Nov 2020 09:15:31 GMT
Content-Type: text/html
<HTML> 
一個包含圖檔的頁面
  <IMG SRC="/image.gif">
</HTML>           

HTTP1.0通信過程

HTTP /1.1

1995年是不平凡的一年,網景公司和微軟開啟浏覽器大戰,誰都想當老大。1999年HTTP/1.1釋出并成為标準,寫入RFC,以為以後不管是網關還是APP等,隻要你要使用HTTP,就得遵守這個标準。

  • 繼續增加了PUT等方法
  • 允許持久連接配接

随着檔案越來越大,圖檔等資訊越來越複雜,如果每一次上傳下載下傳檔案都需要建立連接配接斷開連接配接的過程将增加大量的開銷。為此,提出了持久連接配接,也就是一次TCP連接配接可以具有多個HTTP請求。當然持久連接配接是可選擇的,如果考慮關閉,隻需要使用Connecttion:close關閉即可。長連接配接如下圖所示

長連接配接

  • 強制要求Host頭

我們知道,在電商系統中,經常會因為促銷活動導緻流量飙升,為了緩解流量,其中有種方法即加緩存或者加伺服器。如果是單台伺服器負載過大,資料庫可能分庫分表。資料結構算法中分而治之方法亦是如此。那麼HTTP中,同樣的道理,如果檔案太大,就大檔案切分為小檔案塊發送。

HTTP /2

HTTP/1.1的出現,幾年間出來大量牛掰的網際網路公司,發展實在是太快,但是HTTP1.1中這幾點成為诟病

  • 原因1 TCP自帶慢啟動

顧名思義,"慢啟動"從0到1循循漸進。轎車啟動不會按下按鈕就直接起飛,而是緩慢調節到适合的速度。這不是挺好的?為什麼會帶來性能問題呢。我們知道一個頁面有靜态資料,動态頁面,很多小檔案在加載的過程中就會直接發起請求,這樣導緻太多的請求都會經曆慢啟動過程,花費時間太多。

  • 原因2 多條TCP連接配接帶寬競争

帶寬固定,多條TCP連接配接同時發起競争帶寬資源,由于各個TCP連接配接之間沒有通信機制,也無法得知哪些資源優先級更高,進而導緻想快速下載下傳的資源反而延遲下載下傳。

  • 原因3 頭部阻塞

阻塞,在網絡程式設計中,我們采用異步,多路複用(epoll)方式盡量讓cpu少等待多幹事。在HTTP1.1中,雖然大家共用了一條TCP通道,但是第一個請求沒有結束,第二請求就可能阻塞等待,也就是說不能同時發送接收資料。那麼一個網頁很多資料檔案,如果能夠同時送出請求,讓部分資料檔案能夠得到響應并預處理,這樣就大大的利用了帶寬和cpu的資源。基于這些因素,在HTTP2中出現了新的方案

如何解決頭部阻塞呢?

HTTP是一問一答的模式,大家都在這個隊列排隊導緻堵塞,那就多個隊列并發進行,也就是"對同一個域名發起多個長連接配接"。舉個例子,在火車站排隊買票的時候,如果隻有一個視窗可用,大家隻能苦等,多開幾個視窗就可緩解這個問題。

這個時候使用者數 * 并發數(上限6-8)已經不錯得效果,但是網際網路速度太快,火車站就這麼大,視窗也就這麼多,怎麼辦,建新的火車站進行分流(大部分城市都有什麼東站 西站)。在這裡叫做"域名分片",使用多個域名,這些域名指向同一伺服器。

HTTP/3

HTTP/2看似很完美了吧,但是Google輪子哥可不服,其他人在研究HTTP/2的時候,它們就在琢磨QUIC。那QUIC有啥牛掰的地方呢

QUIC是Google開發的一個基于UDP且能像TCP一樣具有可靠性特點的協定。具備像HTTP/2一樣的應用資料二進制分幀傳輸。其主要解決的問題有兩個。
  1. 進一步解決線頭阻塞問題。通過獨立不同流,讓各個流之間實作互相獨立傳輸,互不幹擾
  2. 切換網絡時的連接配接保持。wifi和3G/4G經常需要來回切換。基于TCP的協定,會因為網絡的切換導緻IP位址的改變。而基于UDP的QUIC協定,及時切換也可以恢複之前與伺服器的連接配接。(這裡推薦大家可以去看看MPTCP)

4 HTTP封包詳解

用戶端與服務端進行互動的資訊為封包。用戶端為請求封包,服務端為響應封包。我們先用wireshark抓一個部落格看看

封包層次結構

GET /article/12 HTTP/1.1
Host: www.xxx.cn
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: SESSION=so9nlsvenminor5abs65sh9dsa           
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 17 May 2020 17:04:29 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: blade-2.0.6-BETA
Content-Encoding: gzip           

請求封包

請求封包通常由三部分組成:

起始行:描述請求或者響應的基本資訊

頭部字段集合:key-value形式說明封包

消息正文:實際傳輸諸如圖檔等資訊。具體如下圖試試

1 請求方法:一共有八種方法選擇,如下圖所示。采用不同的方法擷取不同的資源

HTTP請求方法詳解

說一下非常常見的幾種請求方法

Get:從伺服器中取資源。可以請求圖檔,視訊等

HEAD:和Get類似,但是從伺服器請求的資源不會反悔請求的實體資料,隻會反悔響應頭

POST/PUT:對應于GET,向伺服器發送資料

2 URI

統一資源辨別符(Uniform Resource Identifier),嚴格來說不等于網址,它包含URL和URN,可是URL太出名了以緻于URL="網址"。無論開發,測試運維配置都離不開URI,是以好好掌握。

網絡層的IP主要目的是解決路由和尋址。現在的IP位址按照"."分割,總共2的32次方大約42億。對于計算機來說比較友善,但是對于人類來說還是不容易記憶,此時出現DNS了,他把IP位址映射為我們平時常見的"redis.org",按照"."分割域名,從左到右級别越高,最右邊為"頂級域名"。如下圖所示

域名體系

好了,現在TCP提供可靠(資料不丢失)且位元組流(資料完整性),而且也有友善我們記憶的域名,但是網際網路資源千萬種,也不知道通路什麼(圖檔,文字,視訊一大堆),這個時候URI(統一資源辨別符)出現了,那長啥樣?

URI格式

協定名:HTTP協定,另外還有ftp等協定。告知通路資源時使用什麼協定。

緊接着是分隔符:"://"

主機名:标記網際網路主機,可以是IP也可以是域名,如果不寫端口則使用預設端口,例如HTTP為80,HTTPS為443.

登入認證資訊:登入主機時的使用者名密碼(不建議,直接告訴了别人你的隐私資訊)

主機名:此處可以是域名也可以是IP,如果不寫端口号則是預設端口。比如HTTP預設端口為80,HTTPS預設端口為443

資源所在位置:資源在主機上的位置,使用“/”分隔多級目錄,在這裡是“/en/download.html”。注意,必須"/"開頭

參數:用"?"開始,表示額外的請求要求。通常使用"key=value"的方式存在,如果多個"key=value"則使用"&"相連。

看幾個例子

http://nginx.org/en/download.html

file:///E:/Demo/index/

這裡注意是三個"///",因為前面"://"作為分隔符,資源路徑按照"/"開頭。

既然規則這麼多,對于接收方而言需要完成的解析也需要遵守規則,全球使用者很多使用HTTP,每個國家地區所使用語言不同,HTTP為了能對其進行統一處理,引入了URI編碼,方法比較簡單,将非ASCII或者特殊字元全部轉換為十六進制位元組值,同時在前面加入"%"。比如空格被轉換為"%20","中國"就編碼為"%E4%B8%AD%E5%9B%BD%0A"。

3 請求體

響應封包

狀态行----伺服器響應的狀态

<1> 版本号:使用的HTTP什麼版本

<2> 狀态碼:不同數字代表不同的結果,就如我們在編碼時,通過傳回不同的值代表不同的語義。

狀态碼一共分為5類。

1××:處于中間狀态,還需後續操作

2××:成功收到封包并正确處理

"200 OK"

最常見的成功狀态碼,表示一切正常,用戶端獲得期許的處理結果。如果不是Head請求,那麼在響應頭中通常會有body資料。

"204 No Content"

這個的含義和"200"很相似,不同之處在于它的響應頭中沒有body資料。

"206 Partial Content"

是 HTTP 分塊下載下傳或斷點續傳的基礎,在用戶端發送“範圍請求”、要求擷取資源的部分資料時出現,它與 200 一樣,也是伺服器成功處理了請求,但 body 裡的資料不是資源的全部,而是其中的一部分。狀态碼 206 通常還會伴随着頭字段“Content-Range”,表示響應封包裡 body 資料的具體範圍,供用戶端确認,例如“Content-Range: bytes 0-99/5000”,意思是此次擷取的是總計 5000 個位元組的前 100 個位元組。

3××:重定向到其他資源位置

"301 Moved Permanently"

“永久重定向”,意思是本地請求的資源以及不存在,使用新的URI再次通路。

“302 Found”

“Moved Temporarily”,“臨時重定向”,臨時則所請求的資源暫時還在,但是目前需要用另一個URI通路。

301 和 302 通過在字段Location中表明需要跳轉的URI。兩者最大的不同在于一個是臨時改變,一個是永久改變。舉個例子,有時候需要将網站全部更新為HTTPS,這種永久性改變就需要配置永久的"301"。有時候晚上更新系統,系統暫時不可用,可以配置"302"臨時通路,此時不會做緩存優化,第二天還會通路原來的位址。

“304 Not Modified”

運用于緩存控制。它用于 If-Modified-Since 等條件請求,表示資源未修改,可以了解成“重定向已到緩存的檔案”(即“緩存重定向”)。

4××:請求封包有誤,伺服器無法處理

"400 Bad Request”

通用錯誤碼,表示請求封包有錯誤,但是這個錯誤過于籠統。不知道是用戶端還是哪裡的錯誤,是以在實際應用中,通常會傳回含有明确含義的狀态碼。

“403 Forbidden”

注意了,這一個是表示伺服器禁止通路資源。原因比如涉及到敏感詞彙、法律禁止等。當然,如果能讓用戶端有一個清晰的認識,可以考慮說明拒絕的原因并傳回即可。

“404 Not Found”

這可能是我們都知道且都不想看到的狀态碼之一,它的本意是想要的資源在本地未找到進而無法提供給服務端,但是現在,隻要伺服器"耍脾氣"就會給你傳回 404,而我們也無從得知後面到底是真的未找到,還是有什麼别的原因,

"405 Method Not Allowed"

擷取資源的方法好幾種,我們可以對某些方法進行限制。例如不允許 POST 隻能 GET;

"406 Not Acceptable"

用戶端資源無法滿足用戶端請求的條件,例如請求需要中文但隻有英文;

"408 Request Timeout"

請求逾時,伺服器等待了過長的時間;

"409 Conflict":

多個請求發生了沖突,可以了解為多線程并發時的競态;

413 Request Entity Too Large:

請求封包裡的 body 太大;

414 Request-URI Too Long:請求行裡的 URI 太大;

429 Too Many Requests:用戶端發送了太多的請求,通常是由于伺服器的限連政策;

431 Request Header Fields Too Large:請求頭某個字段或總體太大;

5××:伺服器錯誤,伺服器對請求出的時候發生内部錯誤。

“500 Internal Server Error”

和400 類似,屬于一個通用的錯誤碼,但是伺服器到底是什麼錯誤我們不得而知。其實這是好事,盡量少的将伺服器資源暴露外網,盡量保證伺服器的安全。

“502 Bad Gateway”

通常是伺服器作為網關或者代理時傳回的錯誤碼,表示伺服器自身工作正常,通路後端伺服器時發生了錯誤,但具體的錯誤原因也是不知道的。

“503 Service Unavailable”

表示伺服器目前很忙,暫時無法響應服務,我們上網時有時候遇到的“網絡服務正忙,請稍後重試”的提示資訊就是狀态碼 503。

503 是一個“臨時”的狀态,

暫時比較忙,稍後提供服務。在響應封包中的“Retry-After”字段,訓示用戶端可以在多久以後再次嘗試發送請求。

4 請求體

上面大部分都是涉及到header部分,還有非常重要的body,everybody

頭字段注意事項

<1> 字段名不區分大小寫,例如“Host”也可以寫成“host”,但首字母大寫的可讀性更好;

<2> 字段名裡不允許出現空格,可以使用連字元“-”,但不能使用下劃線"_"。例如,“test-name”是合法的字段名,而“test name”“test_name”是不正确的字段名;

<3> 字段名後面必須緊接着“:”,不能有空格,而":"後的字段之前可以有多個空格;

<4> 字段的順序是沒有意義的,可以任意排列不影響語義;

<5> 字段原則上不能重複,除非這個字段本身的語義允許,例如 Set-Cookie。

HTTP的body常常被分為這幾種的類别

<1> text:超文本text/html,純文字text/plain

<2> audio/video:音視訊資料

<3> application: 可能是文本,也可能是二進制,交給上層應用處理

<4> image: 圖像檔案。image/png等

但是帶寬一定,資料大了通常考慮使用壓縮算法進行壓縮,在HTTP中使用Encoding type表示,常用的壓縮方式有下面幾種

<1> gzip:

一種資料格式,預設且目前僅使用deflate算法壓縮data部分

<2> deflate:

deflate是一種壓縮算法,是huffman編碼的一種加強

<3> br:

br通過變種的LZ77算法、Huffman編碼以及二階文本模組化等方式進行資料壓縮,其他壓縮算法相比,它有着更高的壓塑壓縮效率

使用相應的壓縮方法在帶寬一定的情況下确實有不錯的效果,但是gzip等主要針對檔案壓縮效果不錯,但是對視訊就不行了。這個時候是不是可以使用資料結構中常用的分而治之,大化小再合并的方式呢,

檔案拆分

ok,在封包中使用"Transer-Encoding:chunked"表示,代表body部分資料是分塊傳輸的。另外在body中存在一個content-length字段表示body的長度,兩者不能共存,另外很多時候是流式資料,body中沒有指明content-length,這個時候一般就是chunked傳輸了。

現在可以通過采用分塊的方式增強帶寬的使用率,那他的編碼規則如何呢

<1> 每一個分塊包含長度和資料塊

<2> 長度頭按照CRLF結束

<3> 資料塊在長度快後,且最後CRLF結尾

<4> 使用長度0表示結束,"0\r\n\r\n"

我們還是看圖加深印象

chunked分塊

分塊解決了咋們一部分問題,但是有的時候我們想截斷發送怎麼辦呢。在HTTP中提供了使用字段“Accept - Ranges: bytes”,明确告知用戶端:“我是支援範圍請求的”。那麼Range範圍是怎樣的呢,Range從0開始計算,比如Range:0-5則讀取前6個位元組,伺服器收到了這個請求,将如何回應呢

<1> 合法性檢查。比如一共隻有20位元組,但是請求range:100-200。此時會傳回416----"範圍請求有誤"

<2> 範圍正常,則傳回216,表示請求資料知識一部分

<3> 伺服器端在相應投資端增加Content-Range,格式"bytes x-y/length"。

敲黑闆:斷點續傳怎麼操作?

<1> 檢視伺服器是否支援範圍請求并記錄檔案大小

<2> 多個線程分别負責不同的range

<3> 下載下傳同時記錄進度,即使因為網絡等原因中斷也沒事,Range請求剩餘即可

現在我們通過MIME-TYPE和Encoding-type可以知道body部分的類型,下一步将是對内容進行協商。HTTP中,請求體中使用Accept告訴服務端需要什麼類型資料(我能處理哪些類型資料),響應頭中使用Content表明發送了什麼類型資料,具體如下圖所示

好了,為了各個國家民族順利友好的溝通和明确的區分。HTTP請求頭中使用"type-subtype",注意此時分隔符是"-"。比如en-GB表示英式英語,zh-CN表示常用的漢語,那對于用戶端而言,它通過Accept-Language來标記自己可以了解的自然語言,對應的服務端使用Content-Language表明實體資料使用的語言類型,如下圖所示。

字元集和編碼

Cookie機制

HTTP是無狀态、無記憶的,Cookie機制的出現讓其有記憶功能,是怎麼個實作呢

Cookie

從上圖我們可以知道Cookie是由浏覽器負責存儲,并不是作業系統負責,我們換個浏覽器打開同樣的網頁,服務就認不出來了。

Cookie常見的應用一個是身份識别,一個是廣告追蹤,比如我們在通路網頁視訊或者圖檔的時候,廣告商會悄悄給我們Cookie打上标記,友善做關聯分析和行為分析,進而給我推薦一些相關内容。

HTTP代理

之前介紹的都是一問一答的情景,但是在大部分的情況下都會存在多台伺服器進行通信服務。其中比較常見的就是在請求方與應答方中間增加一個中間代理。

代理

代理作為中間位置,相對請求方為服務端,相當于後端服務端為請求方。代理常見的功能為負載均衡。在負載均衡中需要區分正向代理與反向代理,其中也就會涉及排程算法,比如輪詢,一緻性哈希等。

正向代理與反向代理

那麼問題來了,代理作為隐藏身份,相當于隐藏了真實的用戶端與服務端,那在是不是

5 HTTPS

好人占多數,壞人也不少。總有些要搞壞事,因為HTTP是明文,是以需要想辦法保護明文,進而出現了https。

安全是什麼

安全四要素

機密性

對資訊進行保密,隻能可信的人可以通路(讓我想起時間管理者)。

完整性

資料在傳輸過程中内容不被"篡改"。雖然機密性對資料進行保密了,但是有上策也有下策(hack)

身份認證

證明自己的身份是本人,保證其消息發給可信的人

不可否認

君子一言驷馬難追,說話算數,說過的話做過的事要有所保證

HTTPS

HTTP和HTTPS

從上圖我們知道HTTPS無非是在傳輸層和應用層中間加了一層TLS,正是TLS緊跟當代密碼學的步伐,盡全力的保障使用者的安全。老規矩,我們用wireshark看看長什麼樣子。

TLS

可以看出在互動的過程中多了不少新東西,了解TLS,TLS由SSL握手協定,SSL修改密碼規範協定,SSL警報協定,SSL記錄協定組成。

TLS組成

SSL握手協定:

相對于三次握手

記錄協定

記錄為TLS發送接收資料的基本機關。它的自協定需要通過記錄協定發出。如果多個紀錄資料則可以一個TCP包一次性發出。

警報協定

類似HTTP狀态碼,通過回報不同的消息進行不同的政策。

變更密碼規範協定

告訴對方,從此刻開始,後續的資料将使用加密算法進行加密再傳輸。

對稱加密與非對稱加密

對稱加密

對稱加密,顧名思義,加密方與解密方使用同一鑰匙(秘鑰)。具體一些就是,發送方通過使用相應的加密算法和秘鑰,對将要發送的資訊進行加密;對于接收方而言,使用解密算法和相同的秘鑰解鎖資訊,進而有能力閱讀資訊。

非對稱加密

在對稱加密中,發送方與接收方使用相同的秘鑰。那麼在非對稱加密中則是發送方與接收方使用的不同的秘鑰。其主要解決的問題是防止在秘鑰協商的過程中發生洩漏。比如在對稱加密中,小藍将需要發送的消息加密,然後告訴你密碼是123balala,ok,對于其他人而言,很容易就能劫持到密碼是123balala。那麼在非對稱的情況下,小藍告訴所有人密碼是123balala,對于中間人而言,拿到也沒用,因為沒有私鑰。是以,非對稱密鑰其實主要解決了密鑰分發的難題。如下圖
其實我們經常都在使用非對稱加密,比如使用多台伺服器搭建大資料平台hadoop,為了友善多台機器設定免密登入,是不是就會涉及到秘鑰分發。再比如搭建docker叢集也會使用相關非對稱加密算法。

混合加密

非對稱加密算法,大多數是從數學問題演變而來,運算速度較慢。混合加密所謂取長補短。通信過程中使用RSA等解決密鑰交換問題,然後使用随機數産生的在對稱算法中的會話密鑰,最後使用加密。對方使用私鑰解密得到的密文取出會話秘鑰,這樣就實作了密鑰交換。

通過混淆加密等方式完成了機密性任務,作為Hack隻需要僞造釋出公鑰或者作為之間人竊聽密文。但是我們知道安全是四要素,還需要保證資料的完整性,身份認證等。

摘要

摘要算法可以了解為一種特殊的"單向"加密算法,無密鑰,不可逆。在平時項目中,應該大家都是用過MD5,SHA-1。但是在TLS中使用SHA-2。

假設小A轉賬5000給小C,小A加上SHA-2摘要。網站計算摘要并對比,如果一緻則完整可信。

摘要可信

此時小B想修改小A給的money,這個時候網站計算摘要就會發現不一樣,不可信

摘要不可信

HTTPS請求建立連接配接過程

HTTP握手過程

注意:

  1. 首先通過非對稱加密建立通信過程
  2. 在握手階段,為什麼使用3個随機數,一方面防止「随機數 C」被猜出,另一方增加Session key随機性
  3. Client發出支援的「對稱/非對稱加密」算法
  4. server傳回選用的「對稱/非對稱加密」算法
  5. Client對算法進行确認
  6. Server對算法進行确認

根據wireshak結果,對TLS進一步剖析。TCP三向交握建立連接配接,作為禮貌,Client先打招呼"Client Hello"。裡面包含了Client的版本号、所支援的密碼套件和随機數,如下圖所示

Client Hello

Server端表示尊重,回複"Server Hello",同時進行版本校對,給出随機數(Server Random),從Client算法清單中選擇一個密碼套件,在這裡選擇的"

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"。

cipher Suite

這裡的"

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"什麼意思呢

密碼套件選擇橢圓曲線加RSA、AES、SHA256

雙方通過證書驗證身份。因為本機伺服器選用了ECDHE算法,為了實作密鑰交換算法,它會發送證書後把橢圓曲線的公鑰(Server Params)連帶"Server Key Exchange"消息發送出去。

Server Key Exchange

意思是,剛才混合加密套件比較複雜,給你個算法參數,好好記住,别弄丢了。

ServerHelloDone

随後服務端回複"hello done"告知打招呼完畢

打完招呼完畢後,用戶端對證書進行核實。然後根據密碼套件也生成橢圓曲線的公鑰,用"Client Key Exchange"消息發給伺服器

Client Key Exchange

此時用戶端和服務端都有了密鑰交換的兩個參數(Client Params、ServerParams),然後通過 ECDHE 算法算出了一個新的值,叫“Pre-Master”

有了主密鑰和會話密鑰,用戶端發送“Change Cipher Spec”和“Finished”消息,最後将所有消息加上摘要發送給伺服器驗證。

伺服器同樣發送“Change Cipher Spec”和“Finished”消息,握手結束,開始進行HTTP請求與響應

4 初探域名

我們知道域名的出現讓我們更容易記憶,按照"."分割,越靠近右邊級别越高。域名本質是一個名字空間系統,采用多級域名的方式區分不同的國家,公司等,作為一種身份的辨別。

根域名伺服器(Root DNS Server):管理頂級域名伺服器,傳回“com”“net”“cn”等頂級域名伺服器的 IP 位址;

頂級域名伺服器(Top-level DNS Server):管理各自域名下的權威域名伺服器,比如com 頂級域名伺服器可以傳回 apple.com 域名伺服器的 IP 位址;

權威域名伺服器(Authoritative DNS Server):管理自己域名下主機的 IP 位址,比如apple.com 權威域名伺服器可以傳回 www.apple.com 的 IP 位址**

6 HTTP特點小結

寫到這裡,說它簡單是假的,簡單的東西通常更具有擴充的可能性。根據需求的變更,越來越複雜。

1:靈活且易擴充,他的頭部字段很多都是可定制且可擴充

2:應用廣泛。各個領域都有涉及。"跨平台,跨語言"

3:無狀态。沒有記憶功能,少功能即少占用資源。另外無狀态更容易搭建叢集,通過負載均衡将請求轉發到任意一台伺服器。缺點是無法支援需要連續步驟的"事務"操作。我們知道TCP協定有11種狀态,不同狀态代表通信過程中不同的含義。同樣作業系統中的程序也有執行,就緒,活動阻塞等多種狀态。但是HTTP全程都是"懵逼"無狀态。比如小華請求伺服器擷取視訊X,伺服器覺得可行就發給小華。小華還想擷取視訊Y,這時伺服器不會記錄之前的狀态,也就不知道這兩個請求是否是同一個,是以小華還得告訴伺服器自己的身份。

4:明文。優點是能讓開發人員通過wireshark工具更直覺的調試。缺點即裸奔網際網路,沒隐私可言。

5:可靠傳輸。HTTP為應用層協定,基于TCP/IP,而TCP為“可靠”傳輸協定,是以HTTP能在請求應答中"可靠"傳輸資料。

6:應用層協定。應用層協定很多,其中常用的郵件協定SMTP,上傳下載下傳檔案ftp,預設端口22/23,SSH遠端登入(XSHELL)。這些應用層協定都太專一,而HTTP通過各種頭部字段,實體資料的組合,并綜合緩存代理等功能,不得不說是網絡中的冠希哥。

7 HTTP識别(還原)

這裡說的識别,通過代碼層面(libpcap封裝)實作HTTP的識别,也能進一步展現TCP/IP協定棧的分層特性。先看回憶一下IP頭部格式。

IP頭部

注意頭部中的協定字段,如果此字段值為0x0600則為TCP分組。當知道了是TCP分組後,是不是可以通過TCP頭部中端口(80)就可以判斷為HTTP呢,不能的,很多情況都會使用動态端口的方式進行部署。此時可以通過HTTP中的關鍵字進行判斷。如果為HTTP,再通過頭部字段中的"Content-type",charset等确認文本資訊,編碼方式,最後采用解碼算法進行還原。

8 HTTPS(密文)識别

方法一也是比較直接的方法是直接通過抓包工具,插件配置即可。這裡想給大家分享另一種思路和在Linux持續捕包的方法。
  • 資料集采集
使用python的dpkt庫(pip install dpkt即可),dpkt庫友善對每一層協定進行拆解,同時也能進行流的拆分以及特征的提取。下面舉一個通過無頭浏覽的方式自動化采集流量(ps如果需要較大規模的流量采集則可以考慮使用docker叢集的方式)

Read_pcap

  • 根據所提特征生成npz(實際上是numpy提供的數組存儲方式)
  • 使用開源skearn庫進行模型訓練并識别預測,此處假設使用SVM(僅使用預設參數)

SVM

  • 識别結果(參數進行适度調整定會更好的效果)

識别結果

9 HTTP面試題測試

希望大家看完本文,下面的這些面試是不是可以秒殺了
  • Get和Post差別
  • HTTP與HTTPS差別
  • HTTP通信過程
  • 浏覽器輸入一個位址。到頁面展示中間經曆了哪些步驟?
  • cookies機制和session機制的差別:
  • HTTP請求封包與響應封包格式
  • 一次完整的HTTP請求所經曆的7個步驟
  • HTTP優化方案
  • 不同版本的HTTP差別
  • HTTP優點缺點
  • URI和URL的差別
  • 如何判斷是否為http
  • HTTP 1.1引入分塊傳輸編碼提供了以下幾點好處
  • 長連接配接與短連接配接的差別,以及應用場景
  • 常見web攻擊
  • 站内跳轉和外部重定向有何差別
  • HTTP的keep-alive是幹什麼的?
  • 關于Http 2.0 你知道多少?
  • 講講304緩存的原理
  • HTTP與RPC異同
  • 從傳輸協定來說
RPC既可以基于TCP也可以基于HTTP協定,但是HTTP通常都是基于HTTP
  • 從性能消耗來說
RPC可以基于thrift實作高效二進制傳輸。HTTP大部分通過json實作,無論從位元組大小還是序列化耗時都比t'hrift耗時
  • 從負載均衡來說
RPC基本上自帶負載均衡政策,而HTTP需要配置Nginx實作。