2

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!

RtmY
  • 277
  • 2
  • 9
bryanus
  • 131
  • 1
  • 4
  • Why do you have Nginx in front of an ELB? That seems like an anti-pattern. – Tim Jun 25 '18 at 19:43
  • 1
    @Tim Because the proxy is running nginx/openResty to generate and issue SSL certificates on-the-fly for my multi-tenant SAAS, which is behind an AWS Classic ELB. AFAIK, this was the only way to issue certificates for all of our user's custom domains. AWS ELB doesn't support multiple certificates and even their Application LB only supports 25 certs max. It also isn't feasible to issue certificates onto the backend instances themselves, as they were behind the LB. This solution doesn't touch my app infrastructure. – bryanus Jun 26 '18 at 16:52

1 Answers1

0

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

bryanus
  • 131
  • 1
  • 4
  • 2
    `proxy_pass http://AWS-ELB-URL-HERE;` tells the server to connect to port 80 instead 443 - should it be so? Because you use http instead httpS – djdomi Dec 23 '20 at 05:40