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?

6
  • 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.
    – Tim
    Nov 10, 2018 at 8: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, 2018 at 9: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. Nov 10, 2018 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, 2018 at 17:18
  • Are ifs 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, 2018 at 10:36

2 Answers 2

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();
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"

You must log in to answer this question.

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