21

Please find the below setting which is placed in /etc/nginx/sites-enabled under my site domain name. (mysite.lk)

server {  
   listen   80;
   server_name mysite.lk www.mysite.lk;

   location / {  
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_set_header   Host $http_host;
        proxy_pass "http://127.0.0.1:8080";
   }

} 

The application is running on port 8080 and here I'm redirecting all the 80 traffic to 8080. My website only uses mysite.lk and www.mysite.lk domain names.

Hence, I want to restrict/block all other domains (except mysite.lk and www.mysite.lk) which are coming to this server IP. What is the change that I need to do to achieve this?

I tried numerous things such as answers given in the Why is nginx responding to any domain name?, but was getting errors at the nginx startup.

Please help me out! Thanks.

Update

Found the Answer. A catch-all server block should needed in the top of the config before the given config like below. The code block should be like this.

server {
    return 403;
}

server {
    listen   80;
    server_name mysite.lk www.mysite.lk;
    location / {
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_set_header   Host $http_host;
        proxy_pass "http://127.0.0.1:8080";
   }

}
Amila Iddamalgoda
  • 4,166
  • 11
  • 46
  • 85
  • 1
    You need a *catch-all* server. Your linked answer shows the solution. If you are getting errors in your implementation - you need to fix them. Start at the `/etc/nginx/nginx.conf` file. Are there any other `server` blocks already defined in your system - use `nginx -T` to see the full picture. – Richard Smith Nov 11 '17 at 12:15
  • Thank you very much! It was an error in the server block. Also adding catch-all block "server { return 403; }" before the given block is restricting all other domains. – Amila Iddamalgoda Nov 11 '17 at 12:29
  • It works with port 80 but not with 443. Any ideas why ? – Kornikopic May 16 '18 at 14:02
  • Yeah it works with port 80 but not with 443, why?? – ShivaGaire Nov 01 '18 at 11:14
  • @Kornikopic Did you found any workaround? – ShivaGaire Nov 01 '18 at 11:18

4 Answers4

23

The first server defined in Nginx is treated as the default_server so by just adding one as the default and returning 412 (Precondition Failed) or any another status that best fits your requirements, will help for the subsequent servers to obey the server_name

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 412;
} 

server {
    listen   80;
    server_name mysite.lk www.mysite.lk;
    location / {
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_set_header   Host $http_host;
        proxy_pass "http://127.0.0.1:8080";
   }
}
nbari
  • 25,603
  • 10
  • 76
  • 131
13

All of the above answers are correct. But they all don't work if the other domain tries to access your host via port 443(https/SSL).

To Block access to https requests just add an if block in the https server configuration of your host.

server {

    server_name www.xyz.com xyz.com;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }


    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot

    if ($host = "www.specificdomainyouwanttoblock.com") {
        return 404;
    }

    if ($host = "specificdomainyouwanttoblock.com") {
        return 404;
    }

    # or you can simply add:

    if ($host != "yourdomain.com") {
        return 404;
    }

}
Timothy C. Quinn
  • 3,739
  • 1
  • 35
  • 47
Shekhar
  • 573
  • 2
  • 7
  • 18
  • if you want to account for subdomains in the host checking clause you need to use regex. So something like `$host !~* "\.domain\.com$"` (ends with .domain.com) – Berel Levy Jun 09 '23 at 16:30
0

How about creating a server directive without server_name. Something like this

server {
    listen 80 default_server;

    location / {
        deny all;
    }
}

EDIT Please read http://nginx.org/en/docs/http/request_processing.html In short nginx always looks for best match when it comes to server_names or locations and if it fails to find one it uses the default server.

avpav
  • 452
  • 4
  • 7
0

I have a player script with a Firewall that blocks the websites that are not on my whitelist but it turns out that if I have the Firewall activated, the videos stop working in my Android application, they know how I can modify my Firewall to work with package names Android applications to add my application to the white list and be able to play videos in my app with the Firewall active since I must have it disabled to be able to play the videos in my application.

/**
 * Disable access baseed on referer
 */
if (Data::Get("accs_restriction") == "enable") {
    $domains = explode(",", Data::Get("allowed_domains"));
    $referer = parse_url($_SERVER["HTTP_REFERER"], PHP_URL_HOST);
    if (empty($referer) || !in_array($referer, $domains)) {
        header('HTTP/1.0 403 Forbidden');
        require TEMPLATES . "pages/access_denied.php";
        exit;
    }
}