Nginx

NGINX 作為 Apache 前面的反向代理在 SSL 開啟的情況下不起作用

  • April 23, 2019

我已經閱讀了論壇上的每一篇文章、教程和評論,一旦使用 Nginx 伺服器塊打開 SSL,我仍然無法讓 Nginx 代理正常工作。

Apache 完全設置了用於正常和 ssl 訪問的虛擬主機。Apache 監聽 8081 埠,ports.conf 如下:

NameVirtualHost *:8081
Listen 8081

<IfModule ssl_module>
       Listen 443
</IfModule>

<IfModule mod_gnutls.c>
       Listen 443
</IfModule>

我的 SSL apache vhost 如下:

打開 nginx 並按照以下配置註釋掉 ssl 設置(見下文),一切正常,因為我能夠正確訪問 SSL 和非 SSL 版本的站點。

   server {
       listen 80;
 #      listen 443 ssl;
       server_name foobar.net;

  # ssl on;
  #     ssl_certificate /etc/letsencrypt/live/foobar.net/fullchain.pem;
  #     ssl_certificate_key /etc/letsencrypt/live/foobar.net/privkey.pem;

       location / {
           proxy_pass http://104.236.224.53:8081;
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header X-Forwarded-Proto $scheme;
       }
   }

當我修改上述文件並通過取消註釋伺服器塊中的選項打開 SSL 時,Nginx 和 Apache 在埠 443 上似乎存在衝突?

更新和未註釋的伺服器塊如下所示:

   server {
       listen 80;
       listen 443 ssl;
       server_name foobar.net;

   ssl on;
       ssl_certificate /etc/letsencrypt/live/foobar.net/fullchain.pem;
       ssl_certificate_key /etc/letsencrypt/live/foobar.net/privkey.pem;

       location / {
           proxy_pass http://104.236.224.53:8081;
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header X-Forwarded-Proto $scheme;
       }
   }

嘗試啟動 nginx 返回以下錯誤:

nginx.service - A high performance web server and a reverse proxy server
  Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
  Active: failed (Result: exit-code) since Mon 2017-02-20 18:35:20 EST; 16s ago
 Process: 14505 ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid (code=exited, status=0/SUCCESS
 Process: 14475 ExecReload=/usr/sbin/nginx -g daemon on; master_process on; -s reload (code=exited, status=0/SUCCESS)
 Process: 14671 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=1/FAILURE)
 Process: 14652 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 14328 (code=exited, status=0/SUCCESS)

Feb 20 18:35:18 foo.foobar.net nginx[14671]: nginx: [emerg] listen() to 0.0.0.0:443, backlog 511 failed (98: Address already in use)
Feb 20 18:35:18 foo.foobar.net nginx[14671]: nginx: [emerg] listen() to 0.0.0.0:443, backlog 511 failed (98: Address already in use)
Feb 20 18:35:19 foo.foobar.net nginx[14671]: nginx: [emerg] listen() to 0.0.0.0:443, backlog 511 failed (98: Address already in use)
Feb 20 18:35:19 foo.foobar.net nginx[14671]: nginx: [emerg] listen() to 0.0.0.0:443, backlog 511 failed (98: Address already in use)
Feb 20 18:35:20 foo.foobar.net nginx[14671]: nginx: [emerg] listen() to 0.0.0.0:443, backlog 511 failed (98: Address already in use)
Feb 20 18:35:20 foo.foobar.net nginx[14671]: nginx: [emerg] still could not bind()
Feb 20 18:35:20 foo.foobar.net systemd[1]: nginx.service: Control process exited, code=exited status=1
Feb 20 18:35:20 foo.foobar.net systemd[1]: Failed to start A high performance web server and a reverse proxy server.
Feb 20 18:35:20 foo.foobar.net systemd[1]: nginx.service: Unit entered failed state.
Feb 20 18:35:20 foo.foobar.net systemd[1]: nginx.service: Failed with result 'exit-code'.

我在這裡缺少什麼以使 SSL 從 Nginx 正確傳遞給 Apache?


編輯 1: 為了解決 @Tim 的優點,我將編輯我的主要意圖,讓 Nginx 處理所有請求。

  • 我的初衷是在 Apache 已經被用作我的主伺服器的同一台機器上安裝 Discourse,它本身位於 Docker 容器中。
  • 因為 Discourse 需要訪問 80 埠才能正常執行,所以建議在前面設置 nginx 作為反向代理來處理所有傳入的請求,以便相應地傳遞它們。
  • 我想在後面使用 apache 來處理所有動態內容,讓 nginx 處理靜態位。所以我的理解是,為了做到這一點,需要在 apache 上為每個實例建立一個虛擬主機:http 和 https 請求。也許我在這一點上錯了?

我遵循了DigitalOcean 建議的配置:快進到他們的可選步驟 9。

從邏輯上講,正如我在 apache 上的 HTTP 主機在埠 8081 上偵聽從 nginx 傳遞的請求一樣,我假設我可以做同樣的事情,並且 apache 上的 HTTPS 主機也可以偵聽埠 8081 並優雅地將標頭傳遞給 Apache處理其餘的。這個實現沒有完全工作,因為我被錯誤困擾400: the plain http request was sent to https port

我更進一步並假設可能因為 Apache HTTP 和 HTTPS 都在後面偵聽埠 8081,如果我將分配的 apache HTTP 分配給埠 8081 並將 HTTPS 分配給埠 1443,那麼一切都會無縫執行。同樣,當我嘗試使用此實現通過 HTTPS 訪問我的 worpress 部落格時,它不能完全正常工作,我得到了錯誤

Your browser sent a request that this server could not understand.
Reason: You're speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.

在這一點上,儘管似乎很多人已經讓數字海洋建議的實施能夠正常工作,但我實際上還是沒有想法。:-/

看起來我終於得到了實施,這要歸功於我從你那裡收到的所有回饋。感謝@AlexeyTen 和@Tim

  • 首先,我在 apache 上為 foobar.net 域禁用了 https vhostsudo a2dissite foobar.net.cong
  • 我編輯了 apache ports.conf 文件以僅監聽埠 8081 並刪除了對埠 443 的監聽:
NameVirtualHost *:8081

Listen 8081
  • 最後我編輯了 nginx 伺服器塊來監聽埠 443 並確保註釋掉ssl on。不這樣做是行不通的。
> server {
>     listen 80;
>     listen 443 ssl;
>     server_name foobar.net;
> 
>   # ssl on;
>     ssl_certificate /etc/letsencrypt/live/foobar.net/fullchain.pem;
>     ssl_certificate_key /etc/letsencrypt/live/foobar.net/privkey.pem;
> 
>     location / {
>         proxy_pass http://104.236.224.53:8081;
>         proxy_set_header Host $host;
>         proxy_set_header X-Real-IP $remote_addr;
>         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
>         proxy_set_header X-Forwarded-Proto $scheme;
>     } }

這個實現似乎工作正常,並且無縫地將 php 處理移交給 Apache。

您已經告訴 Apache 和 Nginx 在埠 443 上偵聽,我假設在同一台機器上。只有一個應用程序可以偵聽一個埠。

也許你可以編輯你的問題,告訴我們你為什麼要同時使用 Nginx 和 Apache——你可以用它們中的任何一個來做大多數事情。這樣你可能會得到更有用的建議。

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