nginx responding to unknown host names?

For http:

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

For https, you actually need to point nginx at ssl cert/key. According to documentation, nginx only looks at 'Host' header and does not look at TLS SNI when matching server_name. This means that nginx must be able to accept/decrypt ssl connection before it can inspect the Host header.

server {
    listen 443 ssl default_server;
    server_name _;
    ssl_certificate <path to cert>
    ssl_certificate_key <path to key>
    return 404;
}

The cert/key can be any cert/key e.g. self-signed.

If cert/key are not specified, nginx still tries to use such default_server and fails as it can't accept ssl connection.


The Catchall server block also needs a server_name that you need to set to an invalid value like _. This way, the server block will not match any other hostname and will just be used as last resort. The config will look like this:

server {
    listen 80;
    listen 443 ssl;

    server_name _;

    return 404;
}

The first server {} in your config is like a catch-all so that is why it is being shown. Add something like this before the listen 80 server {}

server {
    return 404;
}

server {
    listen 80;
    server_name web;
    # ...
}

server {
    listen 443;
    server_name web;
    # ...
}