0

I want to restrict access to my site. I only want it accessed through domain.com or www.domain.com. However at the moment i can access it through https://ipaddress

i have created a server block in sites-available like so: I have tried a few things but keep breaking it probably should return 444 from what i have read but not sure where to put that

       server {
    
        server_name your-domain  www.your-domain;
    
       location / {
         proxy_pass http://localhost:5000;
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection keep-alive;
         proxy_set_header Host $host;
         proxy_cache_bypass $http_upgrade;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header X-Forwarded-Proto $scheme;
        }
    
    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/your-domain/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/your-domain/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    
    
    }


server {
if ($host = www.your-domain) {
    return 301 https://$host$request_uri;
} # managed by Certbot


if ($host = your-domain) {
    return 301 https://$host$request_uri;
} # managed by Certbot


    listen 80;
    listen [::]:80;

    server_name your-domain  www.your-domain;
return 404; # managed by Certbot
}
raklos
  • 28,027
  • 60
  • 183
  • 301

1 Answers1

0

For every configuration nginx treats one (or more) server block(s) as the default one(s). The default server block will be used to process any request arriving at the listening port where Host HTTP header mismatch any of the server names specified with the server_name directive in any other defined server blocks (or Host header missing at all). You can specify such a server block explicitly with the default_server flag for the listen directive or the very first server block listening on that port will be used as the default one. This behavior is documented at the How nginx processes a request official documentation page and this SO answer describes some additional details for multihomed systems (well, any system can be counted as multihomed one taking in account lo loopback interface).

So to define a default server explicitly, you can use the following:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    listen 443 default_server ssl;
    listen [::]:443 default_server ssl;
    ssl_certificate /some/path/any.crt;
    ssl_certificate_key /some/path/any.key;
    return 444; # silently drop the connection
    # or you can define some landing page here
}

If you're using a single configuration file instead of multiply vhost definition files, you can place this server block as the very first one and omit those default_server keywords (but I'd rather not, just for reliability).

The above configuration will require a valid certificate/key pair. You don't need to expose your served domain certificate (moreover, generally you don't want an attacker to see what domain is hosted on your server), as any self-signed certificate will be enough for it. For generating a pair of self-signed key/cert in one line you can use the following command:

openssl req -nodes -new -x509 -subj "/CN=localhost" -keyout /some/path/any.key -out /some/path/any.crt

Additionally, using the above default server block, you can greatly simplify the second server block from your configuration:

server {
    listen 80;
    listen [::]:80;
    server_name your-domain www.your-domain;
    return 301 https://$host$request_uri;
    # or if you want to redirect any request to some particular domain, you can explicitly use
    # 'return 301 https://your-domain$request_uri;' or 'return 301 https://www.your-domain$request_uri;'
}

No other requests but for your-domain or www.your-domain domains will be served with it anymore (default server block will be selected for any other request).

Ivan Shatsky
  • 13,267
  • 2
  • 21
  • 37
  • Sorry I'm new to nginx and having a hard time understanding this, i created the certs and added the first snippet to the top of the file pointing to the new certs - getting error "a duplicate default server for 0.0.0.0:80", fyi i have a separate "default" file in site-available too, the one i mentioned is a file configuration for my domain – raklos Nov 03 '21 at 13:56
  • Then I think you should replace that `default` file contents with the default server block from the answer. That way you can add any number of additional files for additional domains you may need to serve in the future while preventing direct IP access (or access with the spoofed `Host` header). – Ivan Shatsky Nov 03 '21 at 14:00
  • I mean you will have two files at the `sites-available` directory - one will be named `your-domain` containing two server blocks exclusively for you domain and the second one will be named `default` containing the default server block from the answer. Additionally you'll need to make a symlink to `your-domain` file in the `sites-enabled` directory and reload nginx config (`nginx -s reload`). Whenever you'll need to host a second domain, you can create `second-domain` file with the configuration excplicitly for the second domain leaving `default` file unchanged. – Ivan Shatsky Nov 03 '21 at 14:12
  • I think this works now thanks, had to comment out first 2 lines (listen 80 default_server;) – raklos Nov 03 '21 at 14:21