Score:-1

Nginx forwarding presenting wrong certificate

cn flag

I have a little problem with nginx. We have two subdomains we own, let's call them domain1.com and domain2.com. For domain2 we don't have further subdomains, for domain1 we have several. If someone enters www.domain2.com I would like nginx to forward the person to https://domain2.com, otherwise just forward them to https://. I achieve this with these two blocks at the end of the config of domain2 in sites-available:

server {
       listen 80;
       server_name domain2.com;
       return 301 https://$http_host$request_uri;
}
server {
       listen 80;
       server_name www.domain2.com;
       return 301 https://domain2.com$request_uri;
}

Also I have HSTS enabled for all subdomains with add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;

Now when navigating to www.domain2.com, browsers throw errors, because nginx presents them with the certificate of a_subdomain.domain1.com. This doesn't happen when directly accessing domain2.com, then nginx presents the correct certificate. And no, reverse proxying the subdomains of domain1 sadly is no option, nginx seems to have trouble with this in combination with PHP.

How do I make nginx to do this right?

Interestingly enough, I also have a config forwarding from a domain we used to host (different from domain1 and domain2) to the new domain on other servers, these forwardings don't have this issue, but the new page probably doesn't use HSTS, so that might be the reason.

Score:0
jp flag

The HSTS policy causes an internal redirect in the browser from HTTP to HTTPS; the browser never sees the redirect configured in Nginx. From the developer tools in the browser (Network tab):

Request URL: http://www.isdm.rwth-aachen.de/
 Request Method: GET
Status Code: 307 Internal Redirect
Referrer Policy: strict-origin-when-cross-origin

The https://www.isdm.rwth-aachen.de/ answers with a certificate from the default server{} block for HTTPS:

$ curl "https://www.isdm.rwth-aachen.de/" -v

* Server certificate:
*  subject: C=DE; ST=Nordrhein-Westfalen; O=RWTH Aachen University; CN=carl.fsmuw.rwth-aachen.de
*  start date: Apr 13 00:00:00 2023 GMT
*  expire date: Apr 12 23:59:59 2024 GMT
*  subjectAltName does not match www.isdm.rwth-aachen.de
* SSL: no alternative certificate subject name matches target host name 'www.isdm.rwth-aachen.de'

To match with this behaviour caused by HSTS, you should configure your Nginx to first redirect to HTTPS and only then between subdomains and apex. All HTTPS subdomains in use should have a valid certificate, which should not be a deal-breaker in the Let's Encrypt era.

  1. As the default (first) server, this already covers the first phase:

    server {
        listen 80;
        server_name isdm.rwth-aachen.de;
        return 301 https://$http_host$request_uri;
    }
    
  2. You could alter the second server{} block to perform the second phase, having a valid certificate for the hostname.

    server {
        listen 443 ssl;
        server_name www.isdm.rwth-aachen.de;
        ssl_certificate /etc/letsencrypt/live/www.isdm.rwth-aachen.de/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/www.isdm.rwth-aachen.de/privkey.pem;
        return 301 https://isdm.rwth-aachen.de$request_uri;
    }
    
jp flag
Or abandon the `www.isdm.rwth-aachen.de` altogether by removing it from the DNS, as `isdm.rwth-aachen.de` is already a subdomain.
Richard Rosner avatar
cn flag
Thanks for the detailed explanation. Is there a way to not have www.isdm.rwth-aachen.de use encryption? We do not rely on letsencrypt, in fact it's not possible for letsencrypt to create certificates for our domains and the process for us to request new server certificates is still quite manual, even though at least we don't have to hand in the requests by hand anymore. And I'm not sure if SANs can be used for this. So not needing yet another certificate would be helpful. Also, deleting the additional DNS entry for www would effectively defeat the whole purpose of the forwarding.
jp flag
The `strict-transport-security: max-age=15768000; includeSubDomains; preload` is cached by the browser for half a year. (As the `preload` not at the domain level `rwth-aachen.de` but at the subdomain `isdm.rwth-aachen.de` it is not preloaded.) Unless you are a time traveler, for not having encryption for the subdomain you would have to remove the `includeSubDomains` from the parent level(s) and wait for six months.
Richard Rosner avatar
cn flag
At least if you don't tell your browser to drop the HSTS policy. Thanks.
Score:0
ws flag

This is mostly comment - but its a bit long....

If someone enters www.domain2.com I would like nginx to forward the person to https://domain2.com

Well, that's a bit silly to start with; you can only have a sungle A record at domain2.com but you can have multiple A or CNAME records at www.domain2.com.

server_name isdm.rwth-aachen.de;

I thought we were talking about [www.]domain[1,2].com

browsers throw errors, because nginx presents them with the certificate of a_subdomain.domain1.com

But you have only shown us a fragment of your config, excluding anything over https and no details of your certificates.

I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.