Friday, August 11, 2017

Force WWW behind an AWS EC2 Load Balancer

Leave a Comment

I've come up with a small issue, we're using a load balancer for a new project, but we cannot force the www. without having a redirect loop between requests.

We're currently using NGINX, and the snippet to redirect is the following:


LOAD BALANCER NGINX CONFIG

# FORGE CONFIG (DOT NOT REMOVE!) include forge-conf/mywebsite.com/before/*;  # FORGE CONFIG (DOT NOT REMOVE!) include upstreams/mywebsite.com;  server {     listen 443 ssl;     listen [::]:443 ssl;     server_name .mywebsite.com;      if ($host !~* ^www\.){         rewrite ^(.*)$ https://www.mywebsite.com$1;     }      # FORGE SSL (DO NOT REMOVE!)     ssl_certificate /etc/nginx/ssl/mywebsite.com/225451/server.crt;     ssl_certificate_key /etc/nginx/ssl/mywebsite.com/225451/server.key;      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;      charset utf-8;      access_log off;     error_log  /var/log/nginx/mywebsite.com-error.log error;      # FORGE CONFIG (DOT NOT REMOVE!)     include forge-conf/mywebsite.com/server/*;      location / {         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;         proxy_set_header Host $http_host;         proxy_set_header X-NginX-Proxy true;          proxy_pass http://370308_app/;         proxy_redirect off;          # Handle Web Socket Connections         proxy_http_version 1.1;         proxy_set_header Upgrade $http_upgrade;         proxy_set_header Connection "upgrade";     } }  # FORGE CONFIG (DOT NOT REMOVE!) include forge-conf/mywebsite.com/after/*; 

HTTP SERVER NGINX CONFIG

# FORGE CONFIG (DOT NOT REMOVE!) include forge-conf/mywebsite.com/before/*;  server {     listen 80;     listen [::]:80;     server_name .mywebsite.com;     root /home/forge/mywebsite.com/public;      if ($host !~* ^www\.){         rewrite ^(.*)$ https://www.mywebsite.com$1;     }      # FORGE SSL (DO NOT REMOVE!)     # ssl_certificate;     # ssl_certificate_key;      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;     ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';     ssl_prefer_server_ciphers on;     ssl_dhparam /etc/nginx/dhparams.pem;      add_header X-Frame-Options "SAMEORIGIN";     add_header X-XSS-Protection "1; mode=block";     add_header X-Content-Type-Options "nosniff";      index index.html index.htm index.php;      charset utf-8;      # FORGE CONFIG (DOT NOT REMOVE!)     include forge-conf/mywebsite.com/server/*;      location / {         try_files $uri $uri/ /index.php?$query_string;     }      location = /favicon.ico { access_log off; log_not_found off; }     location = /robots.txt  { access_log off; log_not_found off; }      access_log off;     error_log  /var/log/nginx/mywebsite.com-error.log error;      error_page 404 /index.php;      location ~ \.php$ {         fastcgi_split_path_info ^(.+\.php)(/.+)$;         fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;         fastcgi_index index.php;         include fastcgi_params;     }      location ~ /\.(?!well-known).* {         deny all;     } }  # FORGE CONFIG (DOT NOT REMOVE!) include forge-conf/mywebsite.com/after/*; 

Thing is, with this config I'm only getting redirect loops from the server.

Help please :D <3

2 Answers

Answers 1

  • I don't think the nginx snippets you provided would cause a redirect loop by themselves.

  • First, you have to figure out whether it's an actual redirect — very often in these questions, the 301 Moved Permanently response gets cached in your browser, and subsequently you see a cached version, instead of a fresh one.

  • Subsequently, you'd have to figure out what is causing the redirect loop:

    • Try adding unique strings to each redirect directive, to see which one would be causing the loop.

      if ($host !~* ^www\.) {return 301 $scheme://www.$host/levelX$request_uri} 
    • Ask yourself why do you have so many redirect directives in the first place — there doesn't seem to be much of a valid reason to have redirect directives both at the front-end load balancer, as well as the backend.

  • If the above doesn't resolve the issue, then you know that the redirect loop is not coming from the files you've provided, and you have to dig deeper — it's possible for it to come from some other files, perhaps one of your include directives, or perhaps a default server of www.example.com is defined elsewhere, which redirects to example.com, or perhaps the redirect is done at the application layer.

Answers 2

After writing the prior general-purpose answer, I Googled "FORGE CONFIG (DOT NOT REMOVE!)", and this was the first result:

https://laracasts.com/discuss/channels/forge/forge-how-to-disable-nginx-default-redirection

inside nginx/forge-conf/be106.net/before/redirect.conf file there is this simple config:

… server_name www.my-domain.net; return 301 $scheme://my-domain.net$request_uri; … 

is there a simple way of removing this without altering the file itself(as it look like bad idea).

So, it appears that the redirect is being caused by the application you're using, so, we found the most likely cause of the loop!


In turn, the appropriate way to configure your application to avoid said loop would be outside of the score of StackOverflow.

However, as a workaround:

  • consider whether you actually need all those forge-conf include directives at the load-balancer level; subsequently, you could fake the appropriate domain to be passed to the backend that would not cause a redirect (provided you remove your own redundant redirects):

    -        proxy_set_header Host $http_host; +        proxy_set_header Host example.com; 
  • note that the reason the forge-conf/example.com/before/redirect.conf directive takes precedence over your own configuration for .example.com is the order of the directive — you could potentially move the /before/* include to be after your own configuration, if such a move would otherwise make sense.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment