How to GeoIP block certain countries in Nginx with MaxMind
I spent too long thinking that ModSecurity was necessary for this, but you can do it with just the ngx_http_geoip2_module
Install nginx along with the module:
apt-get install nginx libnginx-mod-http-geoip2
Download the free GeoLite mmdb database from MaxMind into /etc/nginx/GeoLite2-Country.mmdb
(you can and probably should use their tools to update this automatically).
Create /etc/nginx/conf.d/geoip.conf
with the countries you want to block:
geoip2 /etc/nginx/GeoLite2-Country.mmdb {
auto_reload 5m;
$geoip2_metadata_country_build metadata build_epoch;
$geoip2_data_country_code default=XX source=$remote_addr country iso_code;
}
map $geoip2_data_country_code $block_country {
default 0;
CN 1; # China
RU 1; # Russia
IR 1; # Iran
KP 1; # North Korea
XX 1; # Unknown
}
Then in the server block simply block based on that variable:
server_name _;
location / {
if ($block_country) {
return 403;
}
try_files $uri $uri/ =404;
}
If you want to check if the country code is working before returning 403, you can add the country code to the logs by modifying nginx.conf
:
log_format geoip_combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$geoip2_data_country_code';
access_log /var/log/nginx/access.log geoip_combined;