sslnginxno-www

nginx www redirect to non-www throws cert error


I have added the following server declaration so that all www. prefixed requests should redirect to the non-www url.

server {
  server_name www.spottingquotes.ca;
  return 301 https://spottingquotes.ca$request_uri;
}

This works great with the exception of the url https://www.spottingquotes.ca which throws a certificate error because the cert does not have the www. prefix. You can test this by going into incognito mode and entering the url "https://www.spottingquotes.ca", the site will render, then enter the same url and a cert error is thrown.

My question is, why does this server declaration catch the request properly on the first request but not the subsequent requests. Furthermore, how do I fix this?

A better test is to use the command line which always fails on that url.

I've built this little shell script for testing the various urls which always fails on the https://www.spottingquotes.ca request:

#!/bin/sh
url=spottingquotes.ca
target=https://$url
echo "---> Target:  $target"
curl -I $target
echo "******************************************************************************"

target=https://www.$url
echo "---> Target:  $target"
curl -I $target
echo "******************************************************************************"

target=http://$url
echo "---> Target:  $target"
curl -I $target
echo "******************************************************************************"

target=http://www.$url
echo "---> Target:  $target"
curl -I $target
echo "******************************************************************************"

target=$url
echo "---> Target:  $target"
curl -I $target
echo "******************************************************************************"

Can someone guide me in the right direction or explain why my server declaration is not stripping the https://www. variant properly?

Thanks.

EDIT Here is a sample of the scripts results:

./curl-url.sh 
---> Target:  https://spottingquotes.ca
HTTP/1.1 200 OK
Server: nginx/1.10.2
Date: Mon, 28 Jan 2019 23:40:15 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Status: 200 OK
Cache-Control: max-age=0, private, must-revalidate
Strict-Transport-Security: max-age=604800
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 1; mode=block
X-Request-Id: 41d5365b-161d-4f1e-b117-552849a1a196
X-Download-Options: noopen
ETag: W/"ceabfe116d120b23bf65d7f839911ae6"
X-Runtime: 0.012416
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; base-uri 'self'; block-all-mixed-content; child-src 'self' *.google.com *.stripe.com; connect-src 'self' *.stripe.com; font-src 'self' data: *.cloudflare.com *.gstatic.com; frame-ancestors 'none'; img-src 'self' data: *.google-analytics.com *.cloudflare.com *.gstatic.com *.googleapis.com *.stripe.com *.s3-us-east-2.amazonaws.com; manifest-src 'self'; media-src 'self'; object-src 'none'; sandbox allow-scripts allow-same-origin allow-forms allow-popups allow-modals; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.googleapis.com *.cloudflare.com *.google-analytics.com *.bootstrapcdn.com *.google.com *.gstatic.com *.stripe.com *.atlassian.net *.googletagmanager.com; style-src 'self' 'unsafe-inline' *.googleapis.com *.cloudflare.com *.bootstrapcdn.com; worker-src 'self'; report-uri 'self'
Set-Cookie: Quotr_session=UVBYeGQ0QXBnY2VWMGZvb3RZUHI5bEVuS3ZFT1hYN2pNUlppZHFuZWRoU3RUSC9wdHdMM3l4UGQ4aHdxb1VYVU9yUGVlQjhVRlhXb0h5Y1Y1UWluV0MwbENkcXYydml5TkRjVWVjRG1NODZBa3dyRW94T0ZISWVjZXlkTWpHcDdlSVV2cUtHRy9vbXppNHJndlZ3ZXBBPT0tLUFKc09NWElBc0o2Y1dEbTVndStPbXc9PQ%3D%3D--e382dcfbc60ccb44d155e9f317c553d8a47df2f7; path=/; secure; HttpOnly; SameSite=Lax
X-Powered-By: Phusion Passenger 5.3.0
Strict-Transport-Security: max-age=15768000; includeSubDomains

******************************************************************************
---> Target:  https://www.spottingquotes.ca
curl: (51) SSL: certificate subject name (spottingquotes.ca) does not match target host name 'www.spottingquotes.ca'
******************************************************************************
---> Target:  http://spottingquotes.ca
HTTP/1.1 301 Moved Permanently
Server: nginx/1.10.2
Date: Mon, 28 Jan 2019 23:40:15 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: https://spottingquotes.ca/

******************************************************************************
---> Target:  http://www.spottingquotes.ca
HTTP/1.1 301 Moved Permanently
Server: nginx/1.10.2
Date: Mon, 28 Jan 2019 23:40:15 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: https://spottingquotes.ca/

******************************************************************************
---> Target:  spottingquotes.ca
HTTP/1.1 301 Moved Permanently
Server: nginx/1.10.2
Date: Mon, 28 Jan 2019 23:40:15 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: https://spottingquotes.ca/

******************************************************************************

EDIT EDIT I should mention that we are always redirecting http traffic to https via this server declaration:

server {
  listen 80 default_server;
  listen [::]:80 default_server;

  # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
  return 301 https://spottingquotes.ca$request_uri;
}

Solution

  • The problem ended up being that I didn't have the ssl cert for the www.spottingquotes.ca domain setup. I needed to setup a server block like so:

    server {
      listen *:443 ssl;
      server_name www.spottingquotes.ca;
      # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
      ssl_certificate /etc/letsencrypt/live/www.spottingquotes.ca/fullchain.pem; # managed by Certbot
      ssl_certificate_key /etc/letsencrypt/live/www.spottingquotes.ca/privkey.pem; # managed by Certbot
      ssl_session_timeout 1d;
      ssl_session_cache shared:SSL:50m;
      ssl_session_tickets off;
    
      return 301 https://spottingquotes.ca$request_uri;
    }
    

    Now running the curl script shows every url redirects properly.