Nginx ignore https for all but one domain

httpsnginx

I've recently set up a VPS with a couple of websites running on it (all using different domains) using nginx to proxy requests to the correct application.

I've a valid SSL certificate for one of these domains, so I set up a http->https direct for this:

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

server {
  listen        443 ssl;
  server_name   example.com www.example.com;

  ssl_certificate ..... (etc)
}

For the other domains, I only listen at port 80 and obviously do not set the SSL certificates. Although all domains are accessible, and the HTTPS redirection works as expected for the main domain, I noticed that when I load one of the other domains (without SSL certificate) over HTTPS, nginx is serving the wrong website, instead of… not accepting the connection at all, I would expect?

I tried adding a default config before loading the sites-available:

server {
  listen 80;
  listen 443 ssl;
  return 444;
}

Which gives me the expected behaviour except for the fact that my main domain is not available over HTTPS anymore (although the HTTP->HTTPS redirection is still functional).

This is probably something stupid and/or me not correctly understanding the way nginx handles configuration, but I've no idea where the problem lies exactly. Help?

Best Answer

That's the expected behaviour.

You are using vhosts on a single IP address where you both listen on HTTP and HTTPs. So the server block handling SSL is acting as the default one for everything going to this IP port 443.

You won't be able to refuse the SSL handshake but after it has been completed you can forbid further HTTP requests not targetting a particular domain by adding a separate catch-all server block returning nginx special 444 code.

The generic solution is to have one unique IP for the domain that should support both HTTP and HTTPS and handle all other HTTP vhost on an other IP.