HTTP代理存在兩種形式:
第一種是 RFC 7230 - HTTP/1.1: Message Syntax and Routing(即修訂后的 RFC 2616,HTTP/1.1 協議的第一部分)描述的普通代理。這種代理扮演的是「中間人」角色,對於連接到它的客戶端來說,它是服務端;對於要連接的服務端來說,它是客戶端。它就負責在兩端之間來回傳送 HTTP 報文。
第二種是 Tunneling TCP based protocols through Web proxy servers(通過 Web 代理服務器用隧道方式傳輸基於 TCP 的協議)描述的隧道代理。它通過 HTTP 協議正文部分(Body)完成通訊,以 HTTP 的方式實現任意基於 TCP 的應用層協議代理。這種代理使用 HTTP 的 CONNECT 方法建立連接,但 CONNECT 最開始並不是 RFC 2616 - HTTP/1.1 的一部分,直到 2014 年發布的 HTTP/1.1 修訂版中,才增加了對 CONNECT 及隧道代理的描述,詳見 RFC 7231 - HTTP/1.1: Semantics and Content。實際上這種代理早就被廣泛實現。
本文描述的第一種代理,對應《HTTP 權威指南》一書中第六章「代理」;第二種代理,對應第八章「集成點:網關、隧道及中繼」中的 8.5 小節「隧道」。
第一種普通代理:
第二種隧道代理:HTTP 客戶端通過 CONNECT 方法請求隧道代理創建一條到達任意目的服務器和端口的 TCP 連接,並對客戶端和服務器之間的后繼數據進行盲轉發。
假如我通過代理訪問 A 網站,瀏覽器首先通過 CONNECT 請求,讓代理創建一條到 A 網站的 TCP 連接;一旦 TCP 連接建好,代理無腦轉發后續流量即可。所以這種代理,理論上適用於任意基於 TCP 的應用層協議,HTTPS 網站使用的 TLS 協議當然也可以。這也是這種代理為什么被稱為隧道的原因。對於 HTTPS 來說,客戶端透過代理直接跟服務端進行 TLS 握手協商密鑰,所以依然是安全的,下圖中的抓包信息顯示了這種場景:
可以看到,瀏覽器與代理進行 TCP 握手之后,發起了 CONNECT 請求,報文起始行如下:
CONNECT imququ.com:443 HTTP/1.1
對於 CONNECT 請求來說,只是用來讓代理創建 TCP 連接,所以只需要提供服務器域名及端口即可,並不需要具體的資源路徑。代理收到這樣的請求后,需要與服務端建立 TCP 連接,並響應給瀏覽器這樣一個 HTTP 報文:
HTTP/1.1 200 Connection Established
瀏覽器收到了這個響應報文,就可以認為到服務端的 TCP 連接已經打通,后續直接往這個 TCP 連接寫協議數據即可。通過 Wireshark 的 Follow TCP Steam 功能,可以清楚地看到瀏覽器和代理之間的數據傳遞:
可以看到,瀏覽器建立到服務端 TCP 連接產生的 HTTP 往返,完全是明文,這也是為什么 CONNECT 請求只需要提供域名和端口:如果發送了完整 URL、Cookie 等信息,會被中間人一覽無余,降低了 HTTPS 的安全性。HTTP 代理承載的 HTTPS 流量,應用數據要等到 TLS 握手成功之后通過 Application Data 協議傳輸,中間節點無法得知用於流量加密的 master-secret,無法解密數據。而 CONNECT 暴露的域名和端口,對於普通的 HTTPS 請求來說,中間人一樣可以拿到(IP 和端口很容易拿到,請求的域名可以通過 DNS Query 或者 TLS Client Hello 中的 Server Name Indication 拿到),所以這種方式並沒有增加不安全性。
HTTP代理和HTTPS代理的區別?
用curl對使用代理和不使用代理做分析:
使用代理,隧道模式
curl -v -I https://sp.com.cn/v * Uses proxy env variable https_proxy == 'http://127.0.0.1:808' * Trying 127.0.0.1... * TCP_NODELAY set * Connected to 127.0.0.1 (127.0.0.1) port 808 (#0) * allocate connect buffer! * Establish HTTP proxy tunnel to xx > CONNECT sp.com.cn:443 HTTP/1.1 > Host: xx > User-Agent: curl/7.61.0 > Proxy-Connection: Keep-Alive > < HTTP/1.1 200 OK HTTP/1.1 200 OK < Date: Thu, 29 Apr 2021 03:29:45 GMT Date: Thu, 29 Apr 2021 03:29:45 GMT < Transfer-Encoding: chunked Transfer-Encoding: chunked * Ignoring Transfer-Encoding in CONNECT 200 response < * Proxy replied 200 to CONNECT request * CONNECT phase completed! * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: none CApath: /etc/ssl/certs * TLSv1.3 (OUT), TLS handshake, Client hello (1): * CONNECT phase completed! * CONNECT phase completed! * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Client hello (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
不使用代理:
curl -v -I https://sp.com.cn/v * Trying 121.46.8.134... * TCP_NODELAY set * Connected to sp.com.cn port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: none CApath: /etc/ssl/certs * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Client hello (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
以上可以看使用隧道模式的代理和不使用代理,都會進行TLS握手,隧道模式的代理是安全的。
參考資料:
https://imququ.com/post/x-forwarded-for-header-in-http.html
http://www.verydoc.net/http/00004337.html
https://lilywei739.github.io/2017/01/25/principle_for_http_https.html
https://www.cnblogs.com/a3192048/p/12241059.html
https://blog.csdn.net/dashenpanguge/article/details/105290116
《HTTP 權威指南》