Nginx

HTTPS + Nginx 反向代理 + URL 重寫

  • January 23, 2021

我正在嘗試將所有 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 就是這種二進制格式的一個例子。沒有人知道將來會發明什麼來暴露同樣的問題。

引用自:https://serverfault.com/questions/1050668