Nginx

代理轉發在 Nginx、Laravel、彈性負載均衡器上不起作用

  • March 13, 2021

我有一個 AWS 彈性負載均衡器,它接收域 (bunny.misite.dev) 的 https 請求,請求通過 http 發送到伺服器 Nginx,Laravel 應用程序回答請求。

我遇到的問題是 Laravel 沒有將請求辨識為 Https,而是將請求辨識為 http。

為了解決這個問題,Laravel 提供了一個我使用過的“可信代理”中間件:

<?php

namespace App\Http\Middleware;

use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;

class TrustProxies extends Middleware
{
   /**
    * The trusted proxies for this application.
    *
    * @var array|string|null
    */
   protected $proxies = '*';

   /**
    * The headers that should be used to detect proxies.
    *
    * @var int
    */
   protected $headers = Request::HEADER_X_FORWARDED_FOR |
       Request::HEADER_X_FORWARDED_HOST |
       Request::HEADER_X_FORWARDED_PORT |
       Request::HEADER_X_FORWARDED_PROTO |
       Request::HEADER_X_FORWARDED_AWS_ELB;
}

我的 nginx 配置是

server {
   listen                  80 ;
   listen                  [::]:80 ;

   server_name             bunny.misite.dev;
   server_tokens           off;
   error_log               /home/main/logs/nginx/bunny-master_error.log;
   access_log              /home/main/logs/nginx/bunny-master_access.log main buffer=16k;
   access_log              /var/log/nginx-rc/bunny-master_traffic.log traffic;

   client_max_body_size    256m;

   add_header X-Frame-Options "SAMEORIGIN";
   add_header X-XSS-Protection "1; mode=block";
   add_header X-Content-Type-Options "nosniff";

   root /home/main/webapps/bunny-master/live/public;
   index index.php index.html index.htm;

   location / {
       
       proxy_send_timeout         60;
       proxy_read_timeout         60;
       proxy_buffer_size          128k;
       proxy_buffers              4 256k;
       proxy_busy_buffers_size    256k;
       proxy_temp_file_write_size 256k;
       proxy_connect_timeout       30s;

       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Server-Addr $server_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Forwarded-Port  $server_port;

       proxy_pass http://backend;
   }

   location ~ /\. {
       deny all;
       access_log off;
       log_not_found off;
   }

   location = /favicon.ico {
       log_not_found off;
   }

   location @proxy {
       proxy_send_timeout         60;
       proxy_read_timeout         60;
       proxy_buffer_size          128k;
       proxy_buffers              4 256k;
       proxy_busy_buffers_size    256k;
       proxy_temp_file_write_size 256k;
       proxy_connect_timeout       30s;

       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Server-Addr $server_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_pass http://backend;
   }
}

Laravel >= 5.5 已經使用fideloper/TrustedProxies,所以它應該尊重X-Forwarded-Protoheader 來決定客戶端請求是使用 HTTP 還是 HTTPS。

您的 nginx 配置仍然指定X-Forwarded-Proto為,http因為:

  1. 您指定proxy_set_header X-Forwarded-Prototo $scheme,這是 AWS ELB 在客戶端請求時使用的 URL 方案,並且
  2. nginx 只接收來自 AWS ELB 而不是 HTTPS 的 HTTP 請求。

要解決此問題,您可以:

  • 配置您的 nginx 以接收 HTTPS 請求,或者
  • 將您的設置proxy_set_header X-Forwarded-Proto$http_x_forwarded_proto. AWS ELB應該 X-Forwarded-Proto在進行轉發請求時將請求標頭從客戶端發送到 nginx。如果您確定 AWS ELB 將始終只轉發 HTTPS 請求,您甚至可以設置proxy_set_header X-Forwarded-Protohttps.

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