0

So I´ve removed my default vhost config from /etc/nginx/sites-available/, since I don´t need to catch users accessing a non-existent subdomain (Debian 9).

Problem: When calling a random subdomain with https, f.e. https://abc.example.com, NGINX will apply it´s default behavior and use the first listen 443 server-block it can find in my configuration files. This means that, when a user mistakenly accesses a false subdomain with https, instead of getting a 404 error (like when calling abc.amazon.com or abc.google.com), he will get a red exclamation mark and an certificate name missmatch error (chrome (NET::ERR_CERT_COMMON_NAME_INVALID)), which is way more frightening than a understandable 404 error.
Question: Is there a way to disable this default nginx behavior of using the first ssl server-block it can find?
OH, AND: Even when re-creating the default vhost (I´ve copied a backup of it), NGINX shows the same behavior when accessing a random subdomain with https. Also, firefox will use my port 80 server block to redirect any traffic from http to https://www.example.com$request_uri;. Chrome will redirect http to https when calling a random subdomain, but keep the subdomain (a rule I´ve never specified). Here are my 2 config files in /etc/nginx/sites-available/ I´m currently using.
default (config, updated)

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 404;
}
server {
    listen 443 ssl default_server;
    server_name _;
    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
    return 444;
}

www.example.com (config)

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    include /etc/nginx/snippets/letsencrypt.conf;
    return 301 https://www.example.com$request_uri;
}
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    ssl_dhparam /etc/letsencrypt/live/example.com/dh.pem;
    ssl_protocols TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers on;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    resolver 8.8.8.8;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header x-xss-protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    return 301 https://www.example.com$request_uri;
}
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name www.example.com;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    ssl_dhparam /etc/letsencrypt/live/example.com/dh.pem;
    ssl_protocols TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers on;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    resolver 8.8.8.8;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header x-xss-protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    root /var/www/www.example.com;
    index index.php;
    location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/run/php/php7.0-fpm.sock;
    }

    location / {
            try_files $uri $uri/ =404;
    }
}

EDIT: These are my DNS Records:

(HOST) *   (TYPE) A   (DESTINATION) MYIP
(HOST) @  (TYPE) A   (DESTINATION) MYIP
and some more for ftp, mail etc

How will I have to change the above DNS to only include my Subdomains (imap,webmail,www,smtp)? Also, what is the purpose of the following preconfigured line? Will I have to change it to imap.example.com so that it works properly? (I don't have a mail subdomain)

(HOST) @ (TYPE) MX (MX) 10 (DESTINATION) mail.example.com
5
  • Put the default vhost back. And make a new default vhost for SSL if there isn't one already. Dec 23, 2018 at 20:57
  • @MichaelHampton A self-signed certificate for the default vhost will only make matters worse, since visitors would then encounter a warning about a untrusted certificate. How can big companies like amazon and google handle such https calls, but the average hoster not? Why can´t I just return a 404 error? This is so frustrating...
    – 3x071c
    Dec 23, 2018 at 21:06
  • 1
    Users do not see the default vhost at all. They see the vhost set up to serve your actual web site. The default vhost is only there to catch bots and malicious traffic and send them away. It doesn't matter that it has a self-signed certificate. Dec 23, 2018 at 21:07
  • @MichaelHampton I would have taken this as an answer, but I just can´t stop :) When looking at the webpage you link in your profile (ringingliberty.com) (assuming this is your page) and accessing a random subdomain of it with https (abc.ringingliberty.com) it will also return a 404 error instead of a self-signed certificate warning. How do you handle malicious incoming traffic?
    – 3x071c
    Dec 23, 2018 at 21:13
  • Who knows? You didn't hit my server, so I don't know what you were doing. If you just tried to use "my" IP address, then you hit a CloudFlare frontend server. Oops, try again! Dec 23, 2018 at 21:41

2 Answers 2

2

... user mistakenly accesses a false subdomain with https ... he will get a red exclamation mark and an certificate name missmatch error (chrome (NET::ERR_CERT_COMMON_NAME_INVALID)), which is way more frightening than a understandable 404 error.
Question: Is there a way to disable this default nginx behavior of using the first ssl server-block it can find?

The problem you are trying to solve is not really caused by nginx using the first server block as default.

The problem is instead that you either have no certificate which matches the (sub)domain the client asked for or that you did not configure nginx to provide this certificate if the client accessed this specific subdomain. This means that nginx will not be able to provide the client with a certificate which actually matches the (sub)domain the client has accessed.

Since it is an essential requirement that the certificate of the server must actually match the URL the client will fail in all cases with some frightening error message: either because the subject(s) in the certificate do not match the URL or because the certificate is not issued by a trusted CA (like in case of using a self-signed certificate for the default block) or because the server simply closes the connection if the client tries to access a domain which is not configured (like possible with other web servers).

4
  • This still doesn´t answer my question on how big companies manage to handle random subdomain requests. When accessing abc.google.com, it will return a "ERR_NAME_NOT_RESOLVED" error in chrome. How can I force the same response? Also, somehow nginx is redirecting my http traffic to https for any random subdomain automatically, a rule I´ve never specified.
    – 3x071c
    Dec 24, 2018 at 10:35
  • @SearchingSolutions: ERR_NAME_NOT_RESOLVED is related to DNS and has nothing to do with your nginx setup. You likely have a wildcard DNS record and thus a lookup for any subdomain will return the same IP address which then is used for the client to connect and receive this error. If you don't want this you need to change your DNS setup and not your web server setup. Dec 24, 2018 at 12:18
  • Could you check my edit above and help me :)
    – 3x071c
    Dec 24, 2018 at 17:05
  • @SearchingSolutions: please don't ask a new question (now about DNS configuration) in your existing question about nginx configuration. Also, there is no generic DNS configuration as much as there is no generic web server configuration. How the configuration is done depends on the specific setup. And depending on the setup it might also be that you cannot even change the DNS yourself but must ask you provider. Please check the documentation specific for your setup and provider for clues on how to proceed. Dec 25, 2018 at 7:41
1

I use the following configuration for my SSL default vhost:

server {
    listen 443 ssl default_server;

    ssl_certificate /path/to/self-signed.crt;
    ssl_certificate_key /path/to/key;

    return 444;
}

return 444 is a special nginx return code that closes the connection immediately.

Clients will see an error message about connection issues. That is the best one can do when there is no proper certificate available for a domain.

4
  • As to be seen in the edit I´ve done to my default vhost config in my question, I have implemented the recommended changes. NGINX will still redirect any http traffic to https (on chrome) for any subdomain (Which I never intended) and after the redirect I´ll get a "NET::ERR_CERT_AUTHORITY_INVALID" error from chrome, users will still get a warning about a untrusted certificate...
    – 3x071c
    Dec 24, 2018 at 10:38
  • @SearchingSolutions You enabled HSTS with includeSubDomains. Your browser is now refusing HTTP and changing the URL to HTTPS before it even makes any request. Dec 24, 2018 at 15:16
  • @MichaelHampton Would removing includeSubDomains from the header stop this unintended redirect?
    – 3x071c
    Dec 24, 2018 at 16:46
  • @SearchingSolutions Again, it's not technically a redirect, but it will stop if you remove includeSubDomains AND also clear your browser cache. Dec 24, 2018 at 19:44

You must log in to answer this question.

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