Why is nginx responding to any domain name?

The first server block in the nginx config is the default for all requests that hit the server for which there is no specific server block.

So in your config, assuming your real domain is REAL.COM, when a user types that in, it will resolve to your server, and since there is no server block for this setup, the server block for FAKE.COM, being the first server block (only server block in your case), will process that request.

This is why proper Nginx configs have a specific server block for defaults before following with others for specific domains.

# Default server
server {
    return 404;
}

server {
    server_name domain_1;
    [...]
}

server {
    server_name domain_2;
    [...]
}

etc

** EDIT **

It seems some users are a bit confused by this example and think it is limited to a single conf file etc.

Please note that the above is a simple example for the OP to develop as required.

I personally use separate vhost conf files with this as so (CentOS/RHEL):

http {
    [...]
    # Default server
    server {
        return 404;
    }
    # Other servers
    include /etc/nginx/conf.d/*.conf;
}

/etc/nginx/conf.d/ will contain domain_1.conf, domain_2.conf... domain_n.conf which will be included after the server block in the main nginx.conf file which will always be the first and will always be the default unless it is overridden it with the default_server directive elsewhere.

The alphabetical order of the file names of the conf files for the other servers becomes irrelevant in this case.

In addition, this arrangement gives a lot of flexibility in that it is possible to define multiple defaults.

In my specific case, I have Apache listening on Port 8080 on the internal interface only and I proxy PHP and Perl scripts to Apache.

However, I run two separate applications that both return links with ":8080" in the output html attached as they detect that Apache is not running on the standard Port 80 and try to "help" me out.

This causes an issue in that the links become invalid as Apache cannot be reached from the external interface and the links should point at Port 80.

I resolve this by creating a default server for Port 8080 to redirect such requests.

http {
    [...]
    # Default server block for undefined domains
    server {
        listen 80;
        return 404;
    }
    # Default server block to redirect Port 8080 for all domains
    server {
        listen my.external.ip.addr:8080;
        return 301 http://$host$request_uri;
    }
    # Other servers
    include /etc/nginx/conf.d/*.conf;
}

As nothing in the regular server blocks listens on Port 8080, the redirect default server block transparently handles such requests by virtue of its position in nginx.conf.

I actually have four of such server blocks and this is a simplified use case.


I was unable to resolve my problem with any of the other answers. I resolved the issue by checking to see if the host matched and returning a 403 if it did not. (I had some random website pointing to my web servers content. I'm guessing to hijack search rank)

server {
    listen 443;
    server_name example.com;

    if ($host != "example.com") {
        return 403;
    }

    ...
}

To answer your question - nginx picks the first server if there's no match. See documentation:

If its value does not match any server name, or the request does not contain this header field at all, then nginx will route the request to the default server for this port. In the configuration above, the default server is the first one...

Now, if you wanted to have a default catch-all server that, say, responds with 404 to all requests, then here's how to do it:

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

Note that you need to specify certificate/key (that can be self-signed), otherwise all SSL connections will fail as nginx will try to accept connection using this default_server and won't find cert/key.


You should have a default server for catch-all, you can return 404 or better to not respond at all (will save some bandwidth) by returning 444 which is nginx specific HTTP response that simply close the connection and return nothing

server {
    listen       80  default_server;
    server_name  _; # some invalid name that won't match anything
    return       444;
}

Tags:

Nginx