1

I'm new to Nginx, I want to block direct IP address access to my server and redirect wildcard domain to my main website. Here is why I got so far in /etc/nginx/sites-available/default:

server {
    listen 80;
    listen [::]:80;
    server_name ~^(www\.)?(?<domain>.+)$;

    if ($domain != "12.13.14.15") {
        return 301 https://mainwebsite.com/$domain;
    }

    return 404;
}

Everything seems to be working fine with the config above, but later I found that Nginx if is evil, also when the domain doesn't exist in my main website's database it will show 404 not found page on the mainwebsite.com.

What I'm trying to achieve are:

  1. Block direct IP address access without using if.
  2. Redirect wildcard domain to my main website if the domain actually exists in my database, else return 404 without redirection. I noticed there is try_files but I'm not sure if it can be used to check an external URL.

Can someone please give me some light?

Rifki
  • 61
  • 3
  • 1
    You're better off using a firewall rather than Nginx. iptables or one of the more user friendly interfaces. I can't recommend one though sorry, I use CloudFlare free in front of my websites and use their firewall. I use fail2ban to automatically add bad requesters to the CloudFlare firewall - [tutorial here](https://www.photographerstechsupport.com/aws-amazon-web-services/protecting-amazon-linux-server-fail2ban-cloudflare-wordpress/). – Tim Nov 10 '18 at 08:36
  • @Tim thanks for your comment, I only want to block people from accessing my website through my server's IP address and return Nginx 404 error page when accessed through IP not blocking visitors by their IP. Apparently, I can access my website either by using `http://domain.tld` or `http://11.12.13.14`. – Rifki Nov 10 '18 at 09:10
  • Use the default `server` block for that. Do not edit it; put the configuration for your own web site into a separate `server` block. – Michael Hampton Nov 10 '18 at 12:49
  • @MichaelHampton I did. My main website server block is located in separated config file `/etc/nginx/sites-available/mainwebsite.com`, my website is a platform for selling domain names, when I list a domain, I need to point that domain to my server IP address so when people visit the domain e.g. `http://domainforsale.tld` they get redirected to `https://mainwebsite.com/domainforsale.tld` and in other case, if the domain is already pointed to my server IP address but it's not listed yet on the main website give them 404 Nginx error instead. – Rifki Nov 10 '18 at 17:18
  • Are `if`s evil? The article you referenced states that "it’s also possible to move ifs to server level (where it’s safe as only other rewrite module directives are allowed within it)." Since you're using the `if` at `server` level, it is safe to do so. – Tommiie Nov 14 '18 at 10:36
  • hi, did my answer help you out? – Antony Gibbs Nov 14 '18 at 14:04

2 Answers2

0

I haven't tested, but I'de guess something like that should work

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name ~^(www\.)?(?<domain>.+)$;

    return 301 https://mainwebsite.com/$domain;

    return 404;
}

server {
    listen 80;
    listen [::]:80;
    server_name 12.13.14.15;

    return 404;
}

If not, you could always use a script (here I show with php, but could be node-js, perl, python, etc...)

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    try_files index.php =404;
}

index.php

<?php

$domain = str_ireplace('www.', '', parse_url($_SERVER['HTTP_HOST'], PHP_URL_HOST));

if($domain == '12.13.14.15') {
    http_response_code(404);
    // include a 404 page?
    // require('404.php');
} else {
    $newURL = 'https://mainwebsite.com/'.$domain;
    header('Location: '.$newURL, 301);
}
exit();
Antony Gibbs
  • 425
  • 2
  • 12
0
# One Block for Main Configuration 
server {
    listen 80;
    listen [::]:80;
    server_name ~^(www\.)?(?<domain>.+)$;
    ..........
} 

Note: I don't recommend to use a Regular expression in the server_name parameter. You can introduce another/multiple server blocks if you want to redirect HTTP to httpd or non-www to www.

Ref : Nginx redirect certbot www to non-www

# Second Block for all nonavailable server.
server {
        listen      80 default_server;
        server_name "";
        return      444;
    }

444 Represent "CONNECTION CLOSED WITHOUT RESPONSE"

Kernelv5
  • 187
  • 6