There are 2 different methods to access a website:

  • Through domain name: example.org.

  • Through IP address: 1.2.3.4.

Some site owners don’t want clients access their website through an IP address. If so, they can configure their nginx server to block such access.

HTTP server

Block IP-based access to a HTTP server is very easy:

server {
    listen              80 default_server;
    server_name         _;
    return              444;
}

444 is an unofficial HTTP status code used by nginx.

HTTPS server

Block IP-based access to a HTTPS server is slightly tricky:

server {
    listen              443 default_server ssl;
    server_name         _;
    ssl_certificate     _.crt;
    ssl_certificate_key _.key;
    return              444;
}

Use OpenSSL to generate _.crt and _.key:

openssl req -x509 -days 3650 -out _.crt -keyout _.key -nodes -subj '/CN=_'

Note that you must add options ssl_certificate and ssl_certificate_key to the default server. The certificate can be self-signed, but must be a valid SSL certificate. Using /dev/null won’t work. Not specifying these options will raise an error (even if the client is accessing another server defined in its own block, with its own domain name and ssl certificate):

no “ssl_certificate” is defined in server listening on SSL port while SSL handshaking …

This is weird. Because with SNI, the request should be routed to that server block and has nothing to do with the default server. It remains a question why nginx must require such a certificate on the default server…