URI結構以下,URL是URI中Web Resource的子集,例如http/ftp協議。
html
HTTP全稱Hypertext Transfer Protocol超文本傳輸協議,主要基於TCP實現的應用層協議,特色有:web
版本變化:算法
TCP握手流程:
ubuntu
三次握手緣由。爲了不因傳輸異常致使包時序問題,一端在發消息時必需要接收到對方的回包確認。例如客戶端因網絡延遲發了兩個SYN,若是沒有第三次握手ACK,則服務端會二次創建鏈接。瀏覽器
四次揮手緣由。一端發送FIN是表示本身不發數據,可是還能夠接收另外一端發送的數據。因此要結束TCP鏈接,須要雙方都FIN+ACK兩次RTT。根據wiki也有能夠經過三次揮手結束鏈接,可是須要同時關閉雙端。
結束TIME_WAIT須要等待2MSL(最大報文段生存時間)才能到CLOSED狀態。一是避免最後的ACK丟白鬚要重發,二是要確保這次鏈接的數據包在網絡中消失,避免跟下次鏈接混淆。安全
請求與響應包:
響應狀態碼分爲1xx臨時響應、2xx成功、3xx重定向、4xx請求錯誤、5xx服務器錯誤。常見狀態碼見附錄。服務器
WebSocket是基於TCP的全雙工通訊協議。背景是web app網絡通訊是基於HTTP協議,每次服務端跟客戶端通訊都須要創建一次HTTP鏈接,WebSocket在應用層從新設計,提供機制可讓web網絡通訊在一個TCP鏈接中實現屢次數據傳輸。
WebSocket與HTTP的聯繫
爲了兼容HTTP服務,WebSocket握手協議是在HTTP基礎上進行擴展。可是WebSocket其餘部分與HTTP無關,徹底是在TCP之上封裝的應用與web的協議,其中包括如下內容:
o 爲瀏覽器添加基於Web Origin標準的安全模型
o 添加了一種尋址和協議命名機制,以支持一個端口上的多種服務和一個IP地址上的多個主機名
o 在TCP之上分層成幀機制,以回到創建TCP的IP數據包機制,但沒有長度限制
o 在代理和其餘中間人的狀況下額外設計一套關閉握手協議網絡
WebSocket URI格式:
ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]session
WebSocket握手頭部:
數據結構
RFC: https://tools.ietf.org/html/rfc6455
HTTPS全稱Hypertext Transfer Protocol Secure,是在HTTP協議中添加TLS/SSL擴展,支持加密數據傳輸。
爲了確保數據在傳輸過程當中不被讀取(加密算法)、篡改(數字簽名)、調包(數字證書),如下對相關術語進行解釋。
加密算法
1.對稱加密
對稱加密算法的特色是算法公開、計算量小、加密速度快、加密效率高。對稱加密有不少種算法,因爲它效率很高,因此被普遍使用在不少加密協議的核心當中。不足之處是,交易雙方都使用一樣鑰匙,安全性得不到保證。常見的對稱加密有 DES、AES 等。
2.非對稱加密
非對稱加密使用一對「私鑰-公鑰」,用私鑰加密的內容只有對應公鑰才能解開,反之亦然。非對稱加密有如下特性:
非對稱加密不須要共享同一份祕鑰,安全性要比對稱加密高,但因爲算法強度比對稱加密複雜,加解密的速度比對稱加解密的速度要慢。常見的非對稱加密有 RSA、ESA、ECC 等。
數字簽名
數字簽名就是用摘要算法提取出源文件的摘要並用私鑰進行加密後的內容。摘要一致則說明文件沒有被篡改過,即便摘要被解密也沒法還原數據內容。
摘要算法有如下特性:
通常使用摘要算法來校驗原始內容是否被篡改。常見的摘要算法有 MD五、SHA 等。
數字證書
數字證書是一個經證書受權中心數字簽名的包含公開密鑰擁有者信息以及公開密鑰的文件,用於認證密匙的有效性。通常會包含公鑰、公鑰擁有者名稱、CA 的數字簽名、有效期、受權中心名稱、證書序列號等信息。
數字證書如何確保列出的用戶就是公鑰的擁有者呢?關鍵點是 CA 的數字簽名,CA會用本身的私鑰將證書內容的摘要進行加密。由於 CA 的公鑰是公開的,任何人均可以用公鑰解密出 CA 的數字簽名的摘要,再用一樣的摘要算法提取出證書的摘要和解密 CA 數字簽名後的摘要比對,一致則說明這個證書沒有被篡改過,能夠信任。
參考: https://www.jianshu.com/p/ffe8c203a471
TLS握手過程:
TLS握手協議分爲基礎握手協議(Basic TLS handshake)與雙向認證協議(Client-authenticated TLS handshake)。雙向認證協議是在Basic基礎上增長了客戶端發送證書的步驟。
基礎流程:
公私鑰交換流程:
TLS 1.3改進
冷啓動握手從2-RTT到1-RTT。
Resumption熱啓動
tls 1.2熱啓動實現方式是發送ClientHello時帶上session ID(缺點是須要每一個鏈接服務器保存session狀態)或者session Ticket(序列化的session),服務端確認後直接返回Finished,而後雙端複用Pre-master secret,這樣只須要1-RTT便可完成握手。可是存在風險是若是Pre-master secret被破解,則session數據就會泄露。
tls 1.3改進了熱啓動方式,達到0-RTT。具體實現是在初次握手後經過加密通道傳輸Pre-Shared Key(用於確認使用者身份,而不是密鑰),客戶端熱啓動時同時傳加密數據以及Pre-Shared Key,服務端若是驗證Pre-Shared Key有效則直接解密數據。
tls 1.3冷熱啓動握手圖見spec,搜索figure便可。
https://tools.ietf.org/html/rfc8446#section-4.2.11
常見攻擊
Downgrade attack。man-in-the-middle攻擊的一種,篡改客戶端請求向服務端協商舊版本的加密方式,而後經過已知的舊版本漏洞破解加密請求。一般服務端去掉向後兼容性就能夠解決問題,可是會犧牲部分可用性。另外tls 1.3標準定義在雙端Finished消息中校驗以前全部握手消息的MAC,若是存在篡改則關閉鏈接。
Replay attack。攻擊者sniff並錄製正常客戶端請求,而後向服務端請求一樣的內容,從而欺騙服務端獲取敏感數據。例如0-RTT的首次數據場景,由於服務端沒法驗證數據來源,因此最好的方式是首次請求避免敏感信息、狀態改變等。
相比HTTP1.x,2.0在如下方面作了改進:
Streams, messages, and frames
HTTP2在應用層引入Binary framing機制將傳輸數據從單一請求-響應包細分紅更小的部分進行數據傳輸,從而能夠更靈活地控制數據,引入多路複用、優先級、數據流控制等傳輸策略。
Binary framing引入Stream、message和frame概念。一個TCP鏈接傳輸多個bidirectional streams(包含stream id跟priority);stream由多個messages構成,message是HTTP消息例如一次request或response,包含一個或多個frames;frame包含不一樣類型的數據,是數據傳輸最小單位,例如header,body爲不一樣的frame,能夠經過stream id進行組裝。
multiplexing單TCP鏈接多路複用
一次TCP鏈接在HTTP1只能一次請求響應,HTTP2將屢次請求響應劃分爲frames,交替(interleave)傳輸,最終在對端根據stream id進行組裝。
Stream prioritization
客戶端給每一個stream分配1-256優先級附在header frame中,再根據stream依賴樹請求服務器。RFC沒有規定服務端的行爲,不一樣的服務提供商可能實現不一樣的處理策略,例如cloudflare根據客戶端優先級將stream劃分爲多個池,每一個池分配必定的帶寬傳輸數據。
cloudflare solution: https://blog.cloudflare.com/better-http-2-prioritization-for-a-faster-web/
RFC: https://tools.ietf.org/html/rfc7540#page-24
HTTP headers壓縮
基本思路是對標準header鍵值用固定字典編碼,自定義鍵值用動態字典編碼,沒法用字典狀況下用Huffman編碼。固定字典是基於RFC標準定義的固定鍵值字符串排列;動態字典是在一次connection過程當中動態更新自定義鍵值字符串;Huffman編碼是用於第一次傳輸自定義鍵值,雙端解碼後在動態字典中更新,第二次傳輸便可用字典方式編碼,Huffman表是RFC基於大量現實header統計的機率表。對自定義頭部用預約義字典或動態字典(隨一次connection更新)編碼。
例子: https://blog.cloudflare.com/hpack-the-silent-killer-feature-of-http-2/
ref: https://tools.ietf.org/html/rfc7541
HTTP/2 Server Push
用於服務端控制資源下發。服務端基於客戶端已有的connection,發送PUSH_PROMISE header frame帶上資源url以及預留的stream id給客戶端,而後傳輸data frame將資源下發給客戶端,期間客戶端也能夠控制Push參數。與通常客戶端請求響應不同的是,Push須要遵照same-origin policy以及服務端必須是authoritative。
RFC: https://tools.ietf.org/html/rfc7540#page-60
HTTP3是將傳輸層的TCP替換爲基於UDP的QUIC協議,應用層對齊實現HTTP1/2的語法,從而解決TCP創建鏈接慢、隊頭擁塞等問題。目前HTTP3與QUIC標準處於Internet-Draft狀態,還要通過Proposed Standard、Internet Standard兩個階段才能正式成爲標準。客戶端Chrome和Firefox僅在主線版本支持,另外也有三方庫支持服務端/客戶端HTTP3,具體見wiki資料。
wiki: https://en.wikipedia.org/wiki/HTTP/3
QUIC最初被提案時是"Quick UDP Internet Connections"的縮寫,是基於UDP的多路複用和安全的通用傳輸層協議。目前客戶端有Chrome、Firefox、Opera、Curl支持,服務端有LiteSpeed、Nginx、Cloudflare支持,截至2019年8月,有3.2%的網站使用QUIC。區別於IETF(Internet Engineering Task Force)的標準QUIC,Google QUIC(gQUIC)本意是設計爲通用協議在Chromium中支持HTTP(S),同時也在跟進支持最新的QUIC標準。QUIC具備如下特性:
o Stream multiplexing
o Stream and connection-level flow control
o Low-latency connection establishment
o Connection migration and resilience to NAT rebinding
o Authenticated and encrypted header and payload
QUIC協議內容:
Connection
與服務端的鏈接。包括握手流程定義,傳輸協議、加密協議協商。connection ID用於定義endpoints之間的QUIC路由,即便某一端ip或端口改變了,也能夠將數據傳輸中的connection遷移到新的地址,而不須要從新傳輸已送達的數據。相似IP報頭的source/destination address,QUIC數據包Packet的header也包含Source Connection ID(非必須)和Destination Connection ID,這兩個ID在雙端定義了Packet歸屬於哪一個connection,用於重組數據。ID在QUIC握手時初始化,鏈接過程當中可能被改變。
Stream
用於傳輸有序字節流數據。分爲單向unidirectional和雙向bidirectional stream。能夠在流程控制(flow control)和限制(stream limits)條件下同時建立任意多個stream傳輸任意大小的數據,可是不能保證不一樣stream中傳輸字節的順序。發送數據是經過STREAM frames帶上stream ID、Offset fields以及data,對端再根據ID和Offset進行重組。
Packet and Frame
關於Packet:
握手流程
下圖是1-RTT握手流程,每行格式是"{packet_type}[{packet_num}]: {frame_type}[{frame_payload}] {frame_type1}[{frame_payload1}] ..."
1.客戶端發送Initial包。包含客戶端Source Connection ID(從0開始遞增)以及TLS握手幀CRYPTO Frame(Client Hello bytes)。
2.服務端發送UDP包。UDP中包括三類Packet。Initial包,包含CRYPTO Frame(Server Hello bytes)以及ACK(請求的packet_num);QUIC握手幀HandShake包,包含CRYPTO Frame(證書);1-RTT encrypted包,包含數據幀STREAM Frame(Stream ID,幀Offset,數據長度以及字節數據)。
3.客戶端發送UDP包。UDP中包括三類Packet。Initial包,包含ACK;HandShake包,包含結束的CRYPTO Frame以及ACK;1-RTT encrypted包,包含返回數據幀STREAM Frame以及ACK。
4.服務端發送UDP包。UDP中包括兩類Packet。數據包1-RTT encrypted以及握手包HandShake。
下圖是QUIC 0-RTT握手流程。與TLS Resumption熱啓動優化思路相似。具體流程見RFC。
流量控制(Flow Control)
流量控制是對接收方的數據緩衝大小限制,從而避免快速發送方碾壓慢速接收方及惡意發送者大量消耗接收方內存的狀況。一樣,爲了限制鏈接內的併發,QUIC終端控制其對端能夠發起的最大累計stream。具體有如下幾項:
鏈接遷移(Connection Migration)
當鏈接一方的地址發生改變,將舊鏈接遷移到新的地址上,避免重傳已接收的數據。
必要條件:
由於QUIC在握手過程當中地址必須不變,因此須要在握手完成以後才能發起鏈接遷移。
除了服務端使用Preferred Address狀況下,遷移只能由客戶端發起。
遷移步驟:
1.探測地址是否可達。客戶端發送PATH_CHALLENGE幀(包含自定義Data),服務端響應PATH_RESPONSE(包含請求的自定義Data)。若是發生超時,則地址不可達。同時爲了確保服務端有可用的connection ID,客戶端能夠發送NEW_CONNECTION_ID幀建立新的connection。
2.(可選)初始化新的connection。重置擁塞控制congestion controller以及擁塞通知ECN capability。
3.發起遷移。客戶端用新地址發送non-probing幀(除了PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID, PADDING之外的幀類型),服務端回包而且驗證客戶端地址,便可完成鏈接遷移。
常見網絡攻擊以及防護方案
Handshake Denial of Service
攻擊方法:其目的在於使目標電腦的網路或系統資源耗盡,使服務暫時中斷或中止,致使其正經常使用戶沒法訪問。例如針對TCP常見的SYN flood attack,不斷髮送SYN包要求服務器創建鏈接,致使全部端口被異常佔用。
QUIC防護方案:加密握手完成後,全部包都是加密而且身份驗證過,不符合的包會被丟棄。
Amplification Attack
攻擊方法:思路是攻擊者僞造目標IP向第三方發起請求,第三方返回更多數據給目標緻使資源耗盡。針對QUIC攻擊的具體實現是攻擊者首先鏈接第三方得到address validation token,而後用此token以及目標IP發起0-RTT請求,僞造目標IP熱啓動,第三方驗證熱啓動token合法,則發送0-RTT響應給目標IP。
防護方案:限制address validation tokens的使用和生命週期,例如短期內不接收多個相同token。
Optimistic ACK Attack
攻擊方法:增長ACK參數中收到數據長度,欺騙服務端傳輸比實際帶寬要多得多的數據。
防護方案:QUIC在發送Packet時會累加packet numbers,因此服務端經過刻意跳過某些packet numbers刻意檢測出客戶端是否惡意發包。
Slowloris Attacks
Stream Commitment Attack
攻擊方法:客戶端建立儘量多的connection或者stream,持續發送少許心跳數據,致使服務端資源被佔用。
防護方案:經過接入層防護,部署QUIC時限制每一個IP的鏈接數、限制長鏈接等。
Stream Fragmentation and Reassembly Attacks
攻擊方法:發送方故意只發送stream部分數據,致使接收方須要建立整個stream大小的buffer或數據結構。或者接收方故意不發送ACK包,致使發送方一直持有並重傳發送數據。
防護方案:根據可用內存限制flow control的window大小,防止內存佔用超過資源。
Stateless Reset Oracle
攻擊方法:思路是攻擊者僞造RESET包使服務端正常鏈接被重置,相似的攻擊有TCP reset injection,最多見的例子是訪問google出現"The connection was reset"。QUIC的RESET包的stateless reset token是由static key以及connection ID計算得出,攻擊者將正常Packet轉發到其餘共享static key而且沒有connection的endpoint,則服務端會誤覺得connection不存在繼而發送RESET包而且重置鏈接。
防護方案:服務端管理共享static key的endpoint,確保Packet能發送到有connection的endpoint。
Version Downgrade
攻擊方法:經過版本協商使用低版本不安全的QUIC。
防護方案:QUIC標準暫無多版本的協商行爲。
QUIC RFC: https://tools.ietf.org/html/draft-ietf-quic-transport-24
QUIC with TLS RFC: https://quicwg.org/base-drafts/draft-ietf-quic-tls.html#name-introduction
中文QUIC RFC: http://docs.wxclimb.top/draft-ietf-quic-transport-zh.html#fc-credit
網絡基礎設施已經基於TCP存在普遍的優化,可是對UDP是限速甚至是禁止。Google在早期實驗中就存在少許鏈接被拒絕的問題。
對於網絡耗時,論文[1]對比了HTTP2跟QUIC+SPDY,在不一樣網絡環境下測試網頁加載時間/資源請求耗時。結論是:
2019年論文[2]對TCP作業界通用的優化,對齊QUIC傳輸層參數,測試不一樣網絡環境下頁面加載/顯示時間。結論是QUIC均優於TCP(HTTP2),弱網環境下優點更明顯。
還有資料[3]從實際應用角度提出對QUIC質疑。例如端對端加密限制網絡鏈路的優化,CPU以及內存佔用高,擁塞控制(congestion control)可能搶佔其餘類型的鏈接帶寬等。
[1]P. Biswal, O. Gnawali, "Does QUIC make the Web faster?", Proc. IEEE GLOBECOM, pp. 1-6, Dec. 2016. http://www2.cs.uh.edu/~gnawali/papers/quic-globecom2016.pdf
[2]"A Performance Perspective on Web Optimized Protocol Stacks: TCP+TLS+HTTP/2 vs. QUIC" arXiv:1906.07415v1 [cs.NI] 18 Jun 2019. https://arxiv.org/pdf/1906.07415.pdf
[3]"QUIC and HTTP/3 : Too big to fail?!" https://calendar.perfplanet.com/2018/quic-and-http-3-too-big-to-fail/
https://en.wikipedia.org/wiki/QUIC#cite_note-QUIC_Design_Doc-3
https://blog.cloudflare.com/the-road-to-quic/
https://yucianga.info/?p=819
經常使用請求碼:
1xx(臨時響應)
表示臨時響應並須要請求者繼續執行操做的狀態代碼。
代碼 說明
100 Continue(繼續) 請求者應當繼續提出請求。 服務器返回此代碼表示已收到請求的第一部分,正在等待其他部分。
101 Switching Protocols(切換協議) 請求者已要求服務器切換協議,服務器已確認並準備切換。
2xx (成功)
表示成功處理了請求的狀態代碼。
代碼 說明
200 OK(成功) 服務器已成功處理了請求。 一般,這表示服務器提供了請求的網頁。
201 Created(已建立) 請求成功而且服務器建立了新的資源。
202 Accepted(已接受) 服務器已接受請求,但還沒有處理。
203 Non-Authoritative Information(非受權信息) 服務器已成功處理了請求,但返回的信息可能來自另外一來源。
204 No Content(無內容) 服務器成功處理了請求,但沒有返回任何內容。
205 Reset Content(重置內容) 服務器成功處理了請求,但沒有返回任何內容。
206 Partial Content(部份內容) 服務器成功處理了部分 GET 請求。
3xx (重定向)
表示要完成請求,須要進一步操做。 一般,這些狀態代碼用來重定向。
代碼 說明
300 Multiple Choices(多種選擇) 針對請求,服務器可執行多種操做。 服務器可根據請求者 (user agent) 選擇一項操做,或提供操做列表供請求者選擇。
301 Moved Permanently(永久移動) 請求的網頁已永久移動到新位置。 服務器返回此響應(對 GET 或 HEAD 請求的響應)時,會自動將請求者轉到新位置。
302 Found(臨時移動) 服務器目前從不一樣位置的網頁響應請求,但請求者應繼續使用原有位置來進行之後的請求。
303 See Other(查看其餘位置) 請求者應當對不一樣的位置使用單獨的 GET 請求來檢索響應時,服務器返回此代碼。
304 Not Modified(未修改) 自從上次請求後,請求的網頁未修改過。 服務器返回此響應時,不會返回網頁內容。
305 Use Proxy(使用代理) 請求者只能使用代理訪問請求的網頁。 若是服務器返回此響應,還表示請求者應使用代理。
307 Temporary Redirect(臨時重定向) 服務器目前從不一樣位置的網頁響應請求,但請求者應繼續使用原有位置來進行之後的請求。
4xx(請求錯誤)
這些狀態代碼表示請求可能出錯,妨礙了服務器的處理。
代碼 說明
400 Bad Request(錯誤請求) 服務器不理解請求的語法。
401 Unauthorized(未受權) 請求要求身份驗證。 對於須要登陸的網頁,服務器可能返回此響應。
403 Forbidden(禁止) 服務器拒絕請求。
404 Not Found(未找到) 服務器找不到請求的網頁。
405 Method Not Allowed(方法禁用) 禁用請求中指定的方法。
406 Not Acceptable(不接受) 沒法使用請求的內容特性響應請求的網頁。
407 Proxy Authentication Required(須要代理受權) 此狀態代碼與 401(未受權)相似,但指定請求者應當受權使用代理。
408 Request Timeout(請求超時) 服務器等候請求時發生超時。
409 Conflict(衝突) 服務器在完成請求時發生衝突。 服務器必須在響應中包含有關衝突的信息。
410 Gone(已刪除) 若是請求的資源已永久刪除,服務器就會返回此響應。
411 Length Required(須要有效長度) 服務器不接受不含有效內容長度標頭字段的請求。
412 Precondition Failed(未知足前提條件) 服務器未知足請求者在請求中設置的其中一個前提條件。
413 Request Entity Too Large(請求實體過大) 服務器沒法處理請求,由於請求實體過大,超出服務器的處理能力。
414 Request-URI Too Long(請求的 URI 過長) 請求的 URI(一般爲網址)過長,服務器沒法處理。
415 Unsupported Media Type(不支持的媒體類型) 請求的格式不受請求頁面的支持。
416 Requested Range Not Satisfiable(請求範圍不符合要求) 若是頁面沒法提供請求的範圍,則服務器會返回此狀態代碼。
417 Expectation Failed(未知足指望值) 服務器未知足"指望"請求標頭字段的要求。
5xx(服務器錯誤)
這些狀態代碼表示服務器在嘗試處理請求時發生內部錯誤。 這些錯誤多是服務器自己的錯誤,而不是請求出錯。
代碼 說明500 Internal Server Error(服務器內部錯誤) 服務器遇到錯誤,沒法完成請求。501 Not Implemented(還沒有實施) 服務器不具有完成請求的功能。 例如,服務器沒法識別請求方法時可能會返回此代碼。502 Bad Gateway(錯誤網關) 服務器做爲網關或代理,從上游服務器收到無效響應。503 Service Unavailable(服務不可用) 服務器目前沒法使用(因爲超載或停機維護)。 一般,這只是暫時狀態。504 Gateway Timeout(網關超時) 服務器做爲網關或代理,可是沒有及時從上游服務器收到請求。505 HTTP Version Not Supported(HTTP 版本不受支持) 服務器不支持請求中所用的 HTTP 協議版本。