Nginx Proxy to AWS ELB not passing HTTPS protocol to Backend Instances

amazon-elbnginxopenrestyPROXYruby-on-rails

This is my first ever question, so please go easy on me!

I'm trying to set up an Nginx proxy server to auto-generate SSL certificates using OpenResty/Lua and LetsEncrypt, within a multi-tenant SAAS platform.

The proxy server is running and certificates are being issued fine. The Nginx config (via OpenResty) is passing off requests to my AWS Elastic (Classic) Load Balancer.

The problem is that the instances behind my ELB do not seem to be receiving the HTTPS protocol, so the links in my websites' navigation, etc. are all HTTP and not HTTPS.

For example, loading https://www.domain.com works, but clicking a link in the navigation shows http://www.domain.com/page.html

Here is my OpenResty/nginx config on the proxy:

http {
  lua_shared_dict auto_ssl 1m;
  lua_shared_dict auto_ssl_settings 64k;
  resolver 8.8.8.8 ipv6=off;

  init_by_lua_block {
    auto_ssl = (require "resty.auto-ssl").new()
    auto_ssl:set("allow_domain", function(domain)
      return true
    end)
    auto_ssl:init()
  }

  init_worker_by_lua_block {
    auto_ssl:init_worker()
  }

  server {
    listen 443 ssl;
    location / {
      proxy_pass http://AWS-ELB-URL-HERE;
      proxy_set_header Host $http_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_certificate_by_lua_block {
      auto_ssl:ssl_certificate()
    }
    ssl_certificate /etc/ssl/resty-auto-ssl-fallback.crt;
    ssl_certificate_key /etc/ssl/resty-auto-ssl-fallback.key;
  }

  server {
    listen 80;
    location /.well-known/acme-challenge/ {
      content_by_lua_block {
        auto_ssl:challenge_server()
      }
    }
  }

  server {
    listen 127.0.0.1:8999;
    client_body_buffer_size 128k;
    client_max_body_size 128k;

    location / {
      content_by_lua_block {
        auto_ssl:hook_server()
      }
    }
  }
}

In an attempt to try and determine if the issue is with my Rails app, I changed the Nginx config to point directly to the instance IP address instead of the ELB. In doing so, all links are https(!), which is what I want!

So at this point, I believe the problem is either a) my Nginx config isn't passing the protocol properly, or b) my ELB is not passing the protocol to the backend instance.

I'm sort of inclined to think that the ELB is the culprit, since everything works as expected when pointing the proxy to the instance IP directly.

So, I have started looking at the ELB configuration and listeners, but have not yet been able to find a configuration that works. Here's what I have now:

enter image description here

I have also tried changing it to:

Load Balancer Protocol: HTTPS (Secure HTTP),
Load Balancer Port: 443,
Instance Protocol: HTTP,
Instance Port: 80

But that didn't work either, and the links are still HTTP.

I am now just guessing at what to do with regards to the Listeners and Ports, trying whichever configuration to see if it works or not. So far nothing.

Does anyone have any insight into what the issue could be and how to fix it? TIA!

Best Answer

ok, I figured it out! I just added an additional directive to the SSL block:

proxy_set_header X-Forwarded-Ssl on;

After restarting nginx, all requests are now passed as https to my ELB and app servers behind it!

Also, for my ELB listeners, I deleted the SSL (Secure TCP) listerner and added:

LB Protocol: HTTPS (Secure HTTP), LB Port: 443, Instance Protocol: HTTP, Instance Port: 80