如何防止 nginx 在 AWS 上從 HTTPS 重定向到 HTTP?
我在 AWS ELB 負載均衡器後面有一個由 nginx 提供服務的網站。負載均衡器上僅啟用了 HTTPS。
請求單個文件或帶有斜杠的目錄可以正常工作。但是,請求沒有尾部斜杠的目錄是行不通的。
原因是,當我請求不帶斜杠的目錄時,nginx 會重定向到帶有斜杠的路徑(沒關係),但它也會從 HTTPS 更改為 HTTP。負載均衡器配置為僅允許 HTTPS,因此不起作用(超時)。
在 nginx 日誌文件中,我可以看到請求到達了 nginx,並且是 nginx 以 301 永久重定向響應(因此這不是負載均衡器設置的問題)。
10.100.10.15 - - [24/Nov/2017:15:41:08 +0000] "GET /admin HTTP/1.1" 301 178 "-" "Wget/1.18 (darwin16.0.0)"
curl
當我通過我看到重定向請求 URL 時:$ curl -v https://example.com/admin * Trying 1.2.3.4... * TCP_NODELAY set * Connected to example.com (1.2.3.4) port 443 (#0) * TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * Server certificate: example.com * Server certificate: Amazon * Server certificate: Amazon Root CA 1 * Server certificate: Starfield Services Root Certificate Authority - G2 > GET /admin HTTP/1.1 > Host: example.com > User-Agent: curl/7.54.0 > Accept: */* > < HTTP/1.1 301 Moved Permanently < Date: Mon, 27 Nov 2017 09:19:05 GMT < Content-Type: text/html < Content-Length: 178 < Connection: keep-alive < Server: nginx < Location: http://example.com/admin/ < X-UA-Compatible: IE=Edge < <html> <head><title>301 Moved Permanently</title></head> <body bgcolor="white"> <center><h1>301 Moved Permanently</h1></center> <hr><center>nginx</center> </body> </html> * Connection #0 to host example.com left intact
我的 nginx 配置文件只是
server { root /var/www; }
/etc/nginx/nginx.conf 在這裡。
我試過
server_name_in_redirect off
了,但沒有任何區別。我想避免將主機名放在配置文件中,因為它被打包到一個 Docker 映像中,然後部署在不同的主機(QA、Prod 等)上。
我希望 nginx 執行此重定向,但仍使用 HTTPS。我能做些什麼?
解決問題的最佳位置是終止 SSL 連接的位置。如果它正在執行
nginx
,您將使用一個proxy_redirect
語句映射http
到標題中https
。Location
我不知道 AWS ELB,所以無法評論如何在那裡修復它。某些情況會導致
nginx
以重定向響應,並且假定該方案與用於連接它的方案相同(即來自 AWS ELB)。AFAIK 有三種方法可以緩解後端nginx
伺服器中的問題。1)從1.11.8版本開始,該
absolute_redirect off;
語句會導致Location
header使用相對URL,即缺少scheme和域名。server { absolute_redirect off; ... }
有關更多資訊,請參閱此文件。
/
2)通過使用try_files
語句來禁止向目錄附加尾隨的行為:server { root /path/to/files; location / { try_files $uri =404; } ... }
有關更多資訊,請參閱此文件。
return
3) 使用顯式語句修復問題。server { root /path/to/files; location ~ [^/]$ { if (-d $request_filename) { return 302 https://$host$uri/$is_args$args; } } location / { } ... }