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:

  1. 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
  2. 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 send X-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 set proxy_set_header X-Forwarded-Proto to https.