Nginx: Block Direct IP Access

Posted in Guide on Mar 22, 2020 (updated Mar 28, 2020)

I like to enforce strict SNI on my servers, preferring to reject requests to domain names that I don't host or the IP address of the server itself. If a default_server isn't configured, Nginx will choose the first server block when there isn't a matching server_name. To avoid this, I've configured an SSL default_server in Nginx that uses a dummy certificate and the NULL cipher. By using the NULL cipher, the web browser won't continue with the request (otherwise, an untrusted certificate warning will appear). The 444 response code tells Nginx to close the connection without sending a response.

server {
        listen      443 ssl default_server;
        listen [::]:443 ssl default_server;

        # Disable logging
        error_log  /dev/null;
        access_log off;

        # Snakeoil TLS to appease Nginx
        ssl_certificate     /etc/ssl/certs/ssl-cert-snakeoil.pem;
        ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
        ssl_stapling        off;
        ssl_ciphers         NULL;

        # Close the connection without sending a response
        return 444;

Now, if you try to connect directly using the server IP address or a domain name that isn't defined, the connection is closed almost immediatly, saving a bit of bandwidth.

What About HTTP?

I've stopped enabling unencrypted HTTP on my servers, leaving only HTTPS available. Cloudflare takes care of the redirection from HTTP to HTTPS for the few clients that make unencrypted requests.