Protecting your Nginx installation from malicious domains pointing to it
When setting up Nginx, it will automatically use your first server definition as the default website to load when someone resolves a domain onto it. Which means anyone can setup their own domain to 'point' to your webserver and instantly 'clone' your website under their own domain. Granted, it wouldn't make sense for any legitimate domain but for spammy domains trying to create 'history' with the search engines in order to become more stealthy down the line are a common thing I observed with my own installations.
The solution, is to explicitly setup the 'default' site for Nginx to NOT load and return a 403 instead. That means that if you haven't explicitly configured a site with an appropriate domain yourself, Nginx will just not respond.
(If you are wondering how I even found out about these malicious sites pointing to my web servers, the answer lies to SEO tools like Ahrefs and Semrush and their ability to find backlinks to your sites. That's how I noticed backlinks to pretty much every available page of my site, figuring out the spammy domains were just configured to point to my webserver.)
Setup the default site to not load
The default site config on Ubuntu lies at /etc/nginx/sites-available/default
.
We need to configure both HTTP and HTTPS to not load. Unfortunately, for nginx to allow HTTPS settings on our site config, we need to provide an SSL key as well. Considering we aren't trying to actually serve anything, we will just revert in using a self signed key that we will generate on our server.
So we are going to:
- Generate a self signed ssl certificate
- Apply configuration for a catchall domain on port 80 and port 443 (ssl), to return 403
Generated the self signed SSL cert
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
Configure /etc/nginx/sites-available/default
Open up the /etc/nginx/sites-available/default
and comment out everything: sudo nano /etc/nginx/sites-available/default
.
Then add the following two server blocks in the end of your file.
server {
# HTTP configuration
listen 80 default_server;
listen [::]:80 default_server;
return 403;
}
server {
# HTTPS/SSL configuration
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
return 403;
}
Save and exit.
To apply the config, run sudo nginx -s reload
. This will also tell you if anything went wrong with the above config.
Now, any domain trying to point to your webserver will get a 403 instead of your actual Nginx default page, or even worse, one of your actual sites.
Notes
- The default_server keyword at the end of the listen entries is what tells Nginx to use this server block as the default block of choice, if the server_name doesn't match with any available config file (instead of the first available server_block which is what allows a malicious domain to point to one of our websites).
- As you can see, we haven't given a server_name value (which would be a domain or set of domains). That means that this server block should match any domain.
- Obviously you cannot have multiple default_server entries on an nginx installation, for the same port (above we have 2 different entries for 2 different ports). If you try to define the default_server keyword to any other config file you will get an error when restarting nginx, as it will not know which one should actually be the default.