nginx: How to prevent an exactly named SSL server block from acting as the catchall for all SSL

Solution 1:

Ideally either I'd like nginx to not serve https at all unless the hostname matches, or for it to redirect to http at the same host.

Neither is possible. The connection from a client that goes to https://foo.example.com/ cannot be accepted by anything but an SSL certificate with "foo.example.com" as one of its names. There is no opportunity to redirect until the SSL connection is accepted.

If you configure each site for SSL, a user who clicks through the certificate error will get the site they requested. If you configure a "catch all" site for SSL that provides only an error page and configure name-based virtual hosting for the one site that is supposed to support SSL, you can serve an error page to clients.

SSL and HTTP virtual hosting just don't play nicely together.

Solution 2:

The only way to do is to create a self-signed SSL certificate and use it to gain control on incoming https requests. You can create your self-signed SSL certificate in a few simple steps outlined in this post.

Let's say you create a self-signed certificate with a filename of server.crt. You would then append the following in your nginx configuration:

server {
    listen  443;

    ssl    on;
    ssl_certificate         /etc/nginx/ssl/server.crt;
    ssl_certificate_key     /etc/nginx/ssl/server.key;

    server_name server1.com;

    keepalive_timeout 60;
    rewrite ^       http://$server_name$request_uri? permanent;
}

You will still get the browser SSL warning message, but at least you'll have control over what happens next.


Solution 3:

Add a catch-all server block and return status code 444. It tells nginx to close the connection before sending any data.

server {
    listen 443 default_server ssl;
    server_name _;
    return 444;
}

Tags:

Nginx

Ssl