15

I have two domains that point to the same server, one we'll call home and one we'll call web.

I'm running nginx on port 80 for HTTP and 443 for HTTPS. In my server definitions, I've defined two servers:

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

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

In practice, it works just fine. However, when I try accessing home, which points to the same IP address as web, I get served web rather than getting a 404 or the like.

How can I configure nginx to 404 requests that don't match a server name? Do I need to define a default server which just bounces things down to 404s?

3 Answers 3

19

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.

6

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;
}
1
  • Unfortunately, on the embedded system that I'm using, this doesn't work and I don't have a way of getting the logs. Upvoting, but unable to verify that this works. Dec 9, 2013 at 18:34
4

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;
    # ...
}
4
  • 2
    Great, but it appears that HTTPS requests still get forwarded to the wrong place. I have SNI compiled into nginx, is there a way to do the same thing for unmatched HTTPS requests? Dec 4, 2013 at 7:09
  • add another for the listen 443 then
    – Mike
    Dec 4, 2013 at 7:45
  • 2
    If I add a server { listen 443 default_server; return 404; }, my other SSL virtual hosts are broken. Dec 4, 2013 at 8:21
  • See my reply - need to specify cert/key because nginx looks at Host header (rather than SNI) for server matching. If cert/key are not specified, nginx still tries to use such default_server and fails as it can't accept ssl connection.
    – andreycpp
    Mar 30, 2017 at 20:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .