在討論 HTTPS Proxy 前, 要先分清楚是在講那件事:
- Proxy 和 client 之間的連線用 HTTPS
- Proxy 允許 client 透過它往外用 HTTPS 連線
前者的好處是保護 client 和 Proxy 之間的連線, client 若是用 Wi-Fi 的話, 可藉此加密所有送出的 HTTP 連線, 防止有人偷聽 Wi-Fi 連線。
後者是本篇要討論的對象: Web Proxy 是否能支援 client 對外的 HTTPS 連線? 又是如何作到的? 畢竟 HTTPS 是基於 SSL 連線的 HTTP, 既然資料都用 SSL 加密了, Proxy 看不到 HTTP header 和 body, 要怎麼作好 Web Proxy 的角色?
用 HTTP tunnel
Proxy 接受 HTTP 1.1 的 CONNECT method, 讓 client 用 CONNECT 對外打通一個 TCP 連線 (又稱 HTTP tunnel), 然後只作 TCP packet forwarding, 於是 client 要作什麼都可以。比方說用 TCP 連線作 SSL handshake 轉成加密連線, 接著就可以走 HTTPS, SPDY 或 HTTP 2 了。
這個作法下, Proxy server 不知道 client 對外傳的內容, 只能經手封包, 不能作其它事。
置換 HTTPS 的 certificate
Proxy 一樣接受 CONNECT method 建立 HTTP tunnel, 不過在 SSL handshake 時, 換掉目的地 Web Server 回傳的 certificate, 改用 Proxy 自己的。然後分別和 client 和外部 Web Server 完成 SSL handshake, 形成這樣的連線:
- client <-> Proxy: 用 Proxy 的 certificate 建立 SSL 連線, 使用 key K1。
- Proxy <-> 外部 Web Server: 用 Web Server 的 certificate 建立 SSL 連線, 使用 key K2。
Proxy 收到 client 的資料先用 K1 解密, 再用 K2 加密傳出去; 資料回來的時候反過來比照辦理。這樣 Proxy 就能得知傳送的內容, 可以作 content filtering (如學校可以擋掉成年人才能看的內容)。
這個作法和 SSL man-in-the-middle attack 一樣, 瀏覽器為了避免這類攻擊, 會檢查 certificate 和對應的 public key 資訊是否一致, 不一致時會跳出警告叫使用者不要繼續使用。
不過在可控制的環境下, IT 部門可以在使用者的電腦上裝上 Proxy 的 certificate, 這樣瀏覽器就不會跳出警告。另一方面, 使用者還是可以點選 HTTPS 的圖示檢查 certificate 資訊, 確認 certificate 是否有被換過, 有的話表示傳輸資料有可能被監聽。有興趣的話可以自己裝 mitmproxy 作一個 transparent proxy 試看看。
自己實作 HTTP client 時, 可以用 certificate pinning 擋掉 man-in-the-middle attack, 原理是只相信自己指定的 certificate, 這樣就會忽視攻擊者裝到作業系統的 root CA。
其它討論
藉由了解 Web Proxy 如何處理 HTTPS, 可以得知: 在沒有對使用者裝置動手腳的情況下, Web Proxy 只能放行但不知道內容, 或是依網域名稱決定是否放行 (無法細到網址, 因為那在 HTTP header 裡)。另外, Proxy 可以透過 HTTP 1.1 CONNECT method 傳的參數或是 SSL handshake 傳的 certificate 資訊得知網域名稱。藉此決定是否要放行某些網域的 HTTPS 連線。
雖然 Google 鼓勵大家多用 HTTPS 並且朝向 HTTP 2 邁進, 不過反向思考一下: 用 HTTP 然後自己在 application logic 裡加密資料, 也許可以讓 API 能用在更廣的地方。在特殊的情境下 (比方回傳無法連線的資訊), 或許值得一試?
參考資料
HTTPS Proxy 相關資料
- Does an HTTPS proxy encrypt traffic between proxy client and server for HTTP requests?
- Filtering HTTPS Traffic With Squid
- SPDY Proxy Examples - The Chromium Projects: 有 client, Proxy 和 Web Server 之間的詳細連線過程 (順便備份在這裡)。
關於 HTTP 1.1 CONNECT method
- CONNECT request to a forward HTTP proxy over an SSL connection?
- RFC 2817 - Upgrading to TLS Within HTTP/1.1: CONNECT method 的正式文件。
關於 Certificate Pinning
- tls - What is certificate pinning? - Information Security Stack Exchange
- ikust/hello-pinnedcerts
- Robert Love · Blog: Everything you Need to Know about HTTP Public Key Pinning (HPKP)
2015-09-29 更新
依 Scott 的建議補上 certificate pinning 和 mitmproxy 的資訊。還有刪掉部份內容
沒有留言:
張貼留言