3

So I've got a server with a single IP and a lot of websites, all hosted under nginx. Here's a very simplified reduction of my actual setup:

server {
    listen 80;
    listen 443 ssl;
    server_name ssl.example.com;
    #...
}

server {
    listen 80;
    server_name nossl.example.com;
    #...
}

If I connect to ssl.example.com:443 everything works, as expected.
If I connect to nossl.example.com:443, it tries to serve the content of ssl.example.com:443.

I've made my peace with the why that happens (it's just how ssl+nginx best-matches a virtual server), I just need to stop it sending content from the wrong site.

Short of buying certificates for all my sites (or issuing my own), or pushing the SSL site off onto its own IP, what are my options here? Can nginx double-check the domain for every SSL request and make sure it matches that server_name?

Oli
  • 1,799
  • 19
  • 27
  • Doesn't the first hit on the related column answer your question already: http://serverfault.com/questions/325485/nginx-how-to-prevent-an-exactly-named-ssl-server-block-from-acting-as-the-catch. If not please explain what is different to this question. – Steffen Ullrich May 03 '14 at 10:14

2 Answers2

4

Add the following virtual server:

server {
  listen 443 ssl;
  server_name _;

  ssl on;
  ssl_certificate /path/to/certificate.crt;
  ssl_certificate_key /path/to/certificate.key;

  return 444;
}

If no host is matching, Nginx will use this one as last resort and send back an error.

It needs a SSL certificate to work but you can generate a self-signed one of these very quickly and that will do. This is better than sharing an otherwise valid, existing certificate for another domain (which throws up errors anyway) because there's less leakage.

Oli
  • 1,799
  • 19
  • 27
Spack
  • 1,604
  • 15
  • 22
  • I like the idea in theory but it's not working here on nginx 1.4.7 – Oli May 03 '14 at 10:25
  • I think I might need to provide it with an actual certificate. I've added `ssl on;` but that's moaning about needing `ssl_certificate`. I'll churn out a self-sign for the whole server and see if that works. – Oli May 03 '14 at 10:28
  • Yup, once the certificate configuration is in there it all works. I've suggested an edit for your post. Please accept it. – Oli May 03 '14 at 10:39
  • Well the strangest thing happened. All was working well but the server has just started spitting out the wrong certificate again. No idea what's going wrong. – Oli May 03 '14 at 18:20
  • 2
    Well apparently the order matters. I had my version of the above out in another file that was being included *later* and that wasn't working. I just moved it to just *above* the proper SSL server code and now it works. – Oli May 04 '14 at 00:18
  • The `server_name _;` and `ssl on;` lines are not mandatory – Finesse Sep 06 '18 at 01:02
1

I tend to think that #2 is the most proper answer, but I have found that the following works as well when placed above the server block of the non-ssl virtual servers.

server {
  listen 443;
  server_name .example.com;
  return 444;
}

Don't use the "ssl" flag.

David Rahrer
  • 103
  • 8
  • `ssl` is required otherwise the vhost will serve HTTPS for all the domains (even if they have their own vhosts) – Finesse Sep 06 '18 at 00:47