NginX – Blocking per IP address or range

Yep I know what your thinking, blocking  by IP inside NginX, shouldn’t you be doing that at firewall level instead? Yes, if it comes from the actual IP, you should. Programs such as Fail2ban provide the functionality to automatically block unscrupulous IPs via iptables thus the traffic never gets anywhere near your software.

The problem comes however when your using a service such as Cloudflare. As far as the firewall is concerned the IP is that of Cloudflare, not the actual end user. Thus we then have to fall back on the next layer, which in this case is NginX. Utilising the RealIP Module we can set the user’s actual IP address into the correct server variable. Once we’ve done this anything running from NginX (PHP-FPM etc.) will see the remote address as the correct one rather than Cloudflare’s IP.

Anyway, to the point, blocking the IPs you don’t like. To do this you simply need to use NginX’s geo module. With this you can compare the provided remote address to a list and set a variable inside the http definition in nginx.conf:

geo $ban_ip {
default 0;
10.1.0.0/24 1;
192.168.0.254 1;
};

Once you’ve set this up you can use that variable inside the individual server definitions to send different http response codes for those specific IP addresses:

if ($ban_ip) {
return 404;
}

or you can tell NginX to simply drop the connection,

if ($ban_ip) {
return 444;
}

which if combined with Cloudflare will show the user Cloudflare’s cached version of your site, so the end user is still getting your site, without your server ever serving their client anything.

Thanks for this lovely snippet of information go to Alexander Azarov.

Leave a Reply