之前有介紹過 SSL 憑證只要放在 Load Balancing 就可以了,不必在每台 Load Balancing 後面的機器都去放置 SSL 憑證,假設我們原有 http://xxx.yyy.com 的網址,在我們打通了 https 之後想要將 http 都強制重新導向到 https,很直覺地我們想到的解決方案就是檢查打進來的 Request URL 如果是 http:// 開頭的就回應重新導向到 https:// 開頭的就行了,但死亡導向之門也就此被打開了。
無論我們是用 URL Rewrite Module 或是寫程式在每個 Request 進來的時候去檢查,都免不了檢查 URL 的開頭是否為 http:// 開頭或是 Request.Url.Scheme 是否為 http?
但問題來了,請看下圖,明明網址列是 https:// 開頭,怎麼到了後端變 http 了?!
如果我們不信邪,還是硬要弄會發生什麼事情? 就開啟了死亡導向之門!
關鍵在於 Load Balancing 大都用代理的方式轉發 Request 到後端服務,服務本身只需提供 http 端口接收來自 Load Balancing 轉發的 Request,即便是 Request 本身是走 https 也都由 Load Balancing 解密完後轉發到後端服務,因此後端服務解析出來的 Request.Url.Scheme 為 http 是正常的。
那該怎麼辦?
Load Balancing 代理轉發的 Request 會在標頭加入代理資訊,其中 HTTP_X_FORWARDED_PROTO
標頭就可以讓我們知道 Load Balancing 代理轉發的 Request 是走 http 還是 https。
在 URL Rewrite 新增規則
我選擇用 URL Rewrite 來解決這樣的問題,檢查進來的 Request 是否符合下面兩個條件,是的話就強制重新導向到 https://xxx.yyy.com/...。
- HTTP_Host 是否是 xxx.yyy.com?
- HTTP_X_FORWARDED_PROTO 是否非 https?
這樣設定之後,躲在 Load Balancing 的後端服務就可以正確地判斷 Request 有沒有走 https 進來。