I want to use 2 server blocks. The first is:
server {
listen 443 ssl http2 fastopen=3 reuseport;
server_name a.example.xyz;
include server_safe.conf;
root /home/www/blog/;
}
The second is:
server {
listen 443 ssl http2;
server_name b.example.xyz;
include server_safe.conf;
}
What I want:
I want the server_name to be valid, that is , if I use a c.example.xyz
to visit my website, both a.example.xyz
,b.example.xyz
,c.example.xyz
is the same IP , the server should block the c.example.xyz
request because it is not in the server_name
.
However, if I enter https://c.example.xyz
, the Nginx will still receive the request and reponse as a.example.xyz
I know HTTP/2 has no host in its header, it has a :authority
instead.
My question is that : How can I reject any other request? I only want to accept the request under(with) the host(:authority)
= a(b).example.xyz
The problem is the first Server block is used by default if no other name matches.
Therefore to achieve what you want, you need to create a default block, before the other two, and have it block or redirect, or show an error page.
The downsides of this are:
Unless you have HTTPS certificates that all the domain names (or use a wildcard cert that covers this), then they will get an error when going to https version of your site and use this default config. Though this would happen under your current set up anyway. There is no way AFAIK to send a block message before the HTTPS negotiation happens.
Older clients that don't support SNI (primarily Windows XP) will go to default config, whereas previously they would have gotten through for Server A as it was the default (though not for server B).
The alternative is to write a redirect rule based on the hostname provided. Not 100% sure how to do this on nginx to be honest but if not possible by default then is possible with ModSecurity. Again it will only take effect after the HTTPS negotiation has happened so still leaves you with a potential incorrect cert problem.