HTTPS + Nginx 反向代理 + URL 重寫
我正在嘗試將所有 HTTPS 流量定向到 Nginx 伺服器,在那裡它將所有請求作為對所有內部伺服器的 HTTP 請求進行處理。到目前為止,我能夠讓下面的模板適用於我的大多數伺服器。
server { listen 443 default ssl; ssl_certificate /etc/letencrypt/live/somesite.com/fullchain.pem; ssl_certificate_key /etc/letencrypt/live/somesite.com/privkey.pem; server_name somesite.com; location ^~ /Service { proxy_pass http://192.168.1.2; } location / { proxy_pass http://192.168.1.3; } }
但是,我必須始終將https://somesite.com/Service>與<http://192.168.1.2/Service匹配才能使上述工作正常進行。
我不能讓https://somesite.com/Service>與<http://192.168.1.2/Hello一起工作。
或者我不能使用http://192.168.1.2:3000將其定向到其他埠,例如https://somesite.com/Service。
例如,當我將上面的內容更改為:
location /Service/ { proxy_pass http://192.168.1.2:80/; } location / { proxy_pass http://192.168.1.3; }
使用以下日誌記錄設置:
log_format upstreamlog '[$time_local] $remote_addr - $remote_user - $server_name to: $upstream_addr: $request upstream_response_time $upstream_response_time msec $msec request_time $request_time'; access_log /var/log/nginx/access.log upstreamlog;
這是我得到的日誌:
[22/Jan/2021:09:56:28 +0000] 172.56.38.95 - - - somesite.com to: 192.168.1.2:80: GET /Service/ HTTP/1.1 upstream_response_time 0.004 msec 1611309388.445 request_time 0.004 [22/Jan/2021:09:56:28 +0000] 172.56.38.95 - - - somesite.com to: 192.168.1.2:80: GET /Service/js/default.cache.a331c8c3.js HTTP/1.1 upstream_response_time 0.000 msec 1611309388.547 request_time 0.002 [22/Jan/2021:09:56:28 +0000] 172.56.38.95 - - - somesite.com to: 192.168.1.2:80: GET /Service/favicon.ico HTTP/1.1 upstream_response_time 0.012 msec 1611309388.757 request_time 0.012 [22/Jan/2021:09:56:28 +0000] 172.56.38.95 - - - somesite.com to: 192.168.1.3:80: GET /api/v1/oauth.json?_=1611309389573 HTTP/1.1 upstream_response_time 0.016 msec 1611309388.771 request_time 0.017
從日誌可以看出前三個fetch都是正確的。第四個是錯的。之後沒有再提出要求。再跟踪一點後,我意識到 192.168.1.2 已經有一個 Nginx 伺服器執行並使用 FastCGI 處理 PHP 頁面。我不知道這是否有區別。
所以我嘗試結合上面的內容使用重寫,但我遇到了一個找不到頁面。我認為它似乎不適用於 HTTPS 也許?因此,它讓我提出瞭如何配置 Nginx 以在外部通過 URL 重寫和 HTTPS 進行反向代理的問題。
請參閱NGINX 文件,第一個範例正是您正在做的,並且解釋得很好:
如果你配置一個
location
帶有 path1 的塊和proxy_pass
帶有 path2 的塊,你最終會得到整個“路徑樹”從 path1 重定位到 path2:server { ... server_name example.net; location /some/path/ { proxy_pass http://www.example.com/link/; } }
如果您要訪問
https://example.net/some/path/blah
它將代理到http://www.example.com/link/blah
.下一個警告是您的原始伺服器返回的內容。它可能會發出一些 HTML、一些 JS、一些 CSS,它們都可以包含 HTTP(S) 連結;其中一些是相對的,但有些不是。非常重要的考慮是
proxy_pass
指令不會指示 Nginx 重寫代理數據中的任何連結。如果存在非相對路徑,它們將保持原樣,並且客戶端會將它們解釋為“超出”代理前綴的指令。正如我們在您的日誌文件中看到的,Web 伺服器在請求 2 上返回一些 Javascript 程式碼:
[22/Jan/2021:09:56:28 +0000] 172.56.38.95 - - - somesite.com to: 192.168.1.2:80: GET /Service/js/default.cache.a331c8c3.js HTTP/1.1 upstream_response_time 0.000 msec 1611309388.547 request_time 0.002
該程式碼可能包含一些非相對路徑,即它有一個以 . 開頭的路徑
/api/
。然後客戶端根據該路徑發出請求,該路徑位於代理樹之外(僅/Service/
現在),我們在第 4 行看到它:[22/Jan/2021:09:56:28 +0000] 172.56.38.95 - - - somesite.com to: 192.168.1.3:80: GET /api/v1/oauth.json?_=1611309389573 HTTP/1.1 upstream_response_time 0.016 msec 1611309388.771 request_time 0.017
Nginx,根據它的配置,正確地在別處代理這個請求(它被
location /
規則擷取)。有幾種方法可以解決這個問題。如果您只使用了一些用於非相對路徑的前綴,並且沒有其他任何東西已經在使用它們,您可以在它們返回時代理它們:
# (inside a "server" block, above "location /" rule) location /api/ { proxy_pass http://www.example.com/api/; }
另一種方法是在 Nginx 中使用 a 安裝過濾器
ngx_http_sub_module
,這將改變服務內容,將所有 URI 更新到新的基礎。請記住,不可能有一種完全防彈的方法來做到這一點。連結不僅可以出現在基於文本的 HTML、CSS 和 JS 文件中,還可以出現在專有的二進製文件中。而且我們事先不知道它們可能包含哪些連結來預防性地代理它們。在最近的過去,Adobe Flash 就是這種二進制格式的一個例子。沒有人知道將來會發明什麼來暴露同樣的問題。