Proxy Forwarding not woking on Nginx, Laravel, Elastic Load Balancer
I have an AWS Elastic Load Balancer that receives https requests for the domain (bunny.misite.dev), the requests are sent to the server Nginx via http and the Laravel App answers the requests.
The problem that I have is that Laravel is not identifying the requests as Https its identifying the requests as http.
For solving this problem Laravel provides a "Trusted proxies" middleware that I have use:
<?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;
}
My nginx configurations are
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;
}
}
Solution 1:
Laravel >= 5.5 already uses fideloper/TrustedProxies
, so it should respect X-Forwarded-Proto
header to decide if client requests is using HTTP or HTTPS.
Your nginx config still specifies X-Forwarded-Proto
as http
because:
- You specified
proxy_set_header X-Forwarded-Proto
to$scheme
, which is the URL scheme used by AWS ELB at the time of client request, and - nginx only receives HTTP requests from AWS ELB instead of HTTPS.
To fix this, you can either:
- Configure your nginx to receive HTTPS requests, or
- Set your
proxy_set_header X-Forwarded-Proto
to$http_x_forwarded_proto
. AWS ELB should sendX-Forwarded-Proto
request header from client to nginx when doing a forward request. If you're sure AWS ELB will always forward only HTTPS requests, you can even setproxy_set_header X-Forwarded-Proto
tohttps
.