Default server with custom 404

I see this question has been asked and answered many times, but I am
unable to
make it work.

On a server with multiple virtual hosts I wish to make a catchall which
responds
to everything with a 404 that reveals no information.

I am running nginx version: nginx/1.8.1 on ubuntu 14.04.

My catchall looks like this

server {
listen 80 default_server;
listen 443 ssl default_server;
allow all;
charset utf-8;
error_page 404 /404.html;
root /mypath/html/;
location = /404.html {
root /mypath/html/;
}
location / {
return 404;
}
}

if I make a fake /etc/hosts dns say dongo.bilbo.com and point at my
server then

http://dongo.bilbo.com/404.html shows me the correct 404 page with no
Nginx
info, however, any other path eg http://dongo.bilbo.com always shows me
the
standard Nginx 404 page.

Is there a way to customize my error page for this case?

I would add that the following works well for my real sites

charset utf-8;
error_page 404 /404.html;
location /404.html {
    root /mypath/html;
    }

and there I do see the 404.html from /mypath/html when I visit missing
pages.

Alternatively is there a way to override nginx’s 404 page so it doesn’t
reveal
the server.

Robin Becker

On Wed, Apr 06, 2016 at 02:26:25PM +0100, Robin Becker wrote:

Hi there,

I see this question has been asked and answered many times, but I am
unable to make it work.

It seems to work for me.

Are you certain that no caching in front of nginx is interfering with
your tests?

What do you see if you do something like

curl -v -H Host:anything http://your-server/should-give-404

?

On a server with multiple virtual hosts I wish to make a catchall
which responds to everything with a 404 that reveals no information.

What information does the default nginx internal 404 response reveal,
that your own file does not? See the “curl -v” response above for the
http headers.

I am running nginx version: nginx/1.8.1 on ubuntu 14.04.

My catchall looks like this

server {
listen 80 default_server;

This will be the default server over any others that have “listen *:80”
(in its various guises). If you have anything like “listen ip” anywhere,
then any connection to that IP will not use this server{}.

You most likely do not have “listen ip” anywhere. But just in case –
this is not necessarily a catch-all.

if I make a fake /etc/hosts dns say dongo.bilbo.com and point at my server then

http://dongo.bilbo.com/404.html shows me the correct 404 page with
no Nginx info, however, any other path eg http://dongo.bilbo.com
always shows me the standard Nginx 404 page.

That’s not what I get.

If you still have the problem, perhaps the debug log will show more
about what is going on.

Is there a way to customize my error page for this case?

What you have done should work. Depending on the rest of your config,
of course.

Alternatively is there a way to override nginx’s 404 page so it
doesn’t reveal the server.

Patch the code and recompile.

You probably don’t want to do that.

f

Francis D. [email protected]

On 06/04/2016 23:14, Francis D. wrote:

Alternatively is there a way to override nginx’s 404 page so it
doesn’t reveal the server.

Patch the code and recompile.

You probably don’t want to do that.

f

I suspect my issue has more to do with me not understanding the way
server names
are matched. I look in vain for some equivalent to apache2ctl -S, but
can’t find it.

I have only one vhost with the default_server present and thought that

listen 80 default_server;

would fire for servers without an explicit match. Some simple testing
reveals
another is matching, but I don’t know which one yet.

As this is a live server I won’t try the debug route there, just bad
luck we got
an IP address that had previous connections to some kind of music
distribution.

Compiling nginx would be a last resort.

Sorry for the noise.

Robin Becker

On Thu, Apr 07, 2016 at 10:31:31AM +0100, Robin Becker wrote:

On 06/04/2016 23:14, Francis D. wrote:

Hi there,

Is there a way to customize my error page for this case?

What you have done should work. Depending on the rest of your config,
of course.

I suspect my issue has more to do with me not understanding the way
server names are matched. I look in vain for some equivalent to
apache2ctl -S, but can’t find it.

nginx documentation links to
How nginx processes a request for the first,
and Command-line parameters for the second.

Very approximately,

nginx -T | grep ‘listen|server’

will indicate your server{} blocks, their contained listen directives,
and their contained server_name directives.

(Except: “nginx -T” isn’t in v1.8.1. So grep in your config file, and
in any files that you “include” in it.)

When you know the IP:port the connection arrives on, plus the hostname
that is requested, you can probably work out which server{} block nginx
will choose to handle the request.

I have only one vhost with the default_server present and thought that

listen 80 default_server;

would fire for servers without an explicit match. Some simple
testing reveals another is matching, but I don’t know which one yet.

For every unique “listen IP” or “listen IP:80” directive that you
have anywhere in your config, add the same line to this server{} with
default_server set.

(Which means: if you have somewhere “listen 127.0.0.1:80;”, then you
add a line “listen 127.0.0.1:80 default_server;” to your catch-all
server block.)

As this is a live server I won’t try the debug route there, just bad
luck we got an IP address that had previous connections to some kind
of music distribution.

Install nginx on your test machine. Configure it there until you are
happy that it does what you want. Then transfer the config to your
production machine.

Good luck with it,

f

Francis D. [email protected]

On 07/04/2016 13:17, Francis D. wrote:

For every unique “listen IP” or “listen IP:80” directive that you
have anywhere in your config, add the same line to this server{} with
default_server set.

(Which means: if you have somewhere “listen 127.0.0.1:80;”, then you
add a line “listen 127.0.0.1:80 default_server;” to your catch-all
server block.)


Ah I begin to see the light, I had thought the default_server attribute
would
force this irrespective of the listen now I see I have to allow
listening with
all the patterns eg IP1:80 IP1:443 IP2:80… that makes things much
clearer. Thank you very much.

Good luck with it,

f


Robin Becker