1

Nginx config is causing too many redirects when using a variable in proxy pass. This is an attempt to use NGINX to reverse proxy to resources in a private subnet. The reverse proxy works fine when using the DNS record directly in proxy pass, yet when passing in a variable it causes too many redirects.

NGINX Config: Which DOES NOT WORK

server {
    listen 443 ssl;

    access_log /var/log/nginx/reverse-access.log;
    error_log /var/log/nginx/reverse-error.log;

    server_name $host;
    rewrite ^/$ https://$host/_dashboards redirect;

    ssl_certificate           /etc/nginx/cert.crt;
    ssl_certificate_key       /etc/nginx/cert.key;

    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

    set $domain_endpoint "${elasticsearch_endpoint}";
    set $cognito_endpoint "${cognito_host}";

    location /_dashboards {
        # Forward requests to Dashboards
        proxy_pass https://$domain_endpoint/_dashboards;

        # Handle redirects to Cognito
        proxy_redirect https://$cognito_endpoint https://$host;

        # Update cookie domain and path
        proxy_cookie_domain $domain_endpoint $host;
        proxy_cookie_path / /_dashboards/;

        # Response buffer settings
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
    }

    location ~ \/(log|sign|fav|forgot|change|saml|oauth2) {
        # Forward requests to Cognito
        proxy_pass https://$cognito_endpoint;
    

        # Handle redirects to Dashboards
        proxy_redirect https://$domain_endpoint https://$host;

        # Update cookie domain
        proxy_cookie_domain $cognito_endpoint $host;
    }
}

The only difference for a working config. Is the proxy_pass under the first location /_dashboards is given the DNS record directly like so

location /_dashboards {
    # Forward requests to Dashboards
    proxy_pass https://vpc-aws-blah-blah-blah.com/_dashboards;

When viewing network traffic in the browser. The request appear to be the same. It makes an initial POST request to a login endpoint with a redirect_uri in the url parameters.

The difference is that after the intial POST the working version makes one GET request, while the non-working version makes repeated GET request

Ivan Shatsky
  • 13,267
  • 2
  • 21
  • 37
Spikerr
  • 311
  • 1
  • 5
  • 16
  • What are `${elasticsearch_endpoint}` and `${cognito_host}`? Where are those variables come from? Also I don't understand what you are trying to achieve with `server_name $host;`. – Ivan Shatsky Jan 14 '22 at 22:53
  • These variables are fed in from Terraform, I can SSH onto the machine and see that they are present. They look no different than if I type the variable in directly into the nginx config. Truthfully I don't know what I am doing with server name either I have put some pieces together from https://github.com/aws-samples/opensearch-in-vpc/blob/main/opensearch-in-vpc-module/proxy_instance_init_script.sh and https://aws.amazon.com/premiumsupport/knowledge-center/opensearch-outside-vpc-nginx/ – Spikerr Jan 14 '22 at 23:07
  • You can't use environment variables in nginx config unless you are using something like OpenResty (and if you are, [here](https://stackoverflow.com/questions/41800071/unable-to-use-environment-variables-in-lua-code) is the solution). Some workarounds described in [this](https://serverfault.com/questions/577370/how-can-i-use-environment-variables-in-nginx-conf) ServerFault thread. – Ivan Shatsky Jan 14 '22 at 23:16
  • 1
    Try: `proxy_pass https://$domain_endpoint;` – Richard Smith Jan 15 '22 at 09:59
  • Removing `_dashboards` worked. Please post it as an answer and I will accept it. Any idea why this was happening ? Was it stuck in a dashboard loop ? @RichardSmith – Spikerr Jan 18 '22 at 17:56

1 Answers1

2

From the documentation:

If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive

You have /_dashboards in both the location and proxy_pass, therefore the replacement changes nothing. So you can remove the optional URI part from the proxy_pass statement.

Also, in the same document:

When variables are used in proxy_pass ..., if URI is specified in the directive, it is passed to the server as is, replacing the original request URI.

So, when you started using variables, if the original request was /_dashboards/foo, the upstream server would only ever receive /_dashboards.

The simplest solution was to remove /_dashboards from the proxy_pass statement.

Richard Smith
  • 45,711
  • 6
  • 82
  • 81