How do I restrict access to my site via plain IP address?
I have a domain, my_domain.com
, that I'd like for visitors to only be able to access by searching for the domain -- I'd also like to block any attempts at accessing this site via my Linode's IP address.
3 Replies
This is a great question! Though the base concepts are the same, I'll go ahead and split this answer into two parts (one for Apache, the other for Nginx).
Apache
The following VirtualHost blocks should provide a good starting point (where default
could also potentially be your Linode's IP address, and domain.com
would be your actual domain name):
<VirtualHost *:80>
ServerName default
DocumentRoot /home/admin/web/xxx.com/public_html
<Location />
Require all denied
</Location>
</VirtualHost>
<VirtualHost *:80>
ServerName domain.com
DocumentRoot /home/admin/web/xxx.com/public_html
</VirtualHost>
The rationale behind this is that requests for your site via your Linode's IP address will end up being sorted into the first VH block, and subsequently blocked. Those who search for your site via its actual domain name will proceed to the second VH block, and will be able to access your site normally.
Nginx
As mentioned before, the thought process behind configuring this with Nginx is pretty similar, if a bit less verbose:
server {
listen 80 default_server;
server_name _;
return 404;
}
Note that the underscore (_) character could also be replaced by your Linode's IP address, as the underscore is a sort-of "catch-all" symbol in this instance.
I found that the Nginx configuration provided here was liable to result in configuration errors, particularly due to default_server
appearing twice.
Instead, I found this Nginx configuration a very reliable means of disabling all access to my web server except from desired.host.name
without such errors occurring:
if ($host != "desired.host.name") {
return 403;
}
You will obviously want to change desired.host.name
to your actual domain name, and you will also want to restart your Nginx service after making these configuration changes.
I found that I needed to duplicate this server configuration in both the port 80 and 443 server
blocks. This may be an important consideration if you are using Let's Encrypt/Certbot or a commercial SSL configuration.
There are a few other important details to consider here:
You may consider extending this basic example to tailor it to your needs. If you'd like to do so, I'd familiarize yourself with the syntax of
if
in Nginx:Should you have multiple domain names or other forms of access you'd like to allow, you will likely need to duplicate this example for each of those domains in each relevant
server
block. However, the~
regular expression operator inif
may be able to consolidate these duplicate statements to an extent (see the above link).if
is Nginx is evil when used in location context:This example is only using
return
, which this page notes is one of the only two 100% safe things to do in this context. However, if you are considering any other modifications to this snippet for your purposes, you would do well to read this page.My web server was not using Cloudflare in front of it. If you are using Cloudflare, you may want to consider the impact of this system and its interactions with Nginx while making these configuration changes.
I regret that I do not have a similar Apache example to share at this time. My testing in this field did not yield consistent results for me, particular in regard to redirect management. However, you may get better mileage than me.
I have found this to be a very reliable, robust, and clean way to limit access to my Nginx server through desired domain names. It is well worth considering in addition to the previously supplied option.