Country Blocking with GeoIP2
Control access by country with MaxMind's accurate geolocation database.
-
Block Bad Actors
Stop attacks from high-risk countries before they reach your app
-
Compliance Ready
Enforce geographic restrictions for GDPR, licensing, or legal requirements
-
Zero Overhead
In-memory database lookup—no external API calls or latency
-
Accurate Data
MaxMind GeoIP2 databases with 99.8% country accuracy
Prerequisites
You'll need a free MaxMind account to download GeoIP2 databases:
- Sign up at maxmind.com/en/geolite2/signup
- Generate a license key in your account
- Save it for the automated update setup
Quick Setup
Step 1: Install GeoIP2 Module
# Install GetPageSpeed repository
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
# Install GeoIP2 module and automatic database updater
dnf -y install nginx-module-geoip2 geoipupdate
Enable in /etc/nginx/nginx.conf:
load_module modules/ngx_http_geoip2_module.so;
Step 2: Configure Database Updates
Edit /etc/GeoIP.conf:
AccountID YOUR_ACCOUNT_ID
LicenseKey YOUR_LICENSE_KEY
EditionIDs GeoLite2-Country GeoLite2-City
Download the databases:
geoipupdate
Enable automatic weekly updates:
systemctl enable --now geoipupdate.timer
Step 3: Configure NGINX
Add to your http block in /etc/nginx/nginx.conf:
# Load GeoIP2 databases
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
auto_reload 60m;
$geoip2_country_code country iso_code;
$geoip2_country_name country names en;
}
Step 4: Block Countries
# Block Russia, China, North Korea
map $geoip2_country_code $blocked_country {
default 0;
RU 1;
CN 1;
KP 1;
}
server {
# ... your server config ...
if ($blocked_country) {
return 403;
}
}
# Only allow US, UK, Canada, Australia
map $geoip2_country_code $allowed_country {
default 0;
US 1;
GB 1;
CA 1;
AU 1;
}
server {
# ... your server config ...
if ($allowed_country = 0) {
return 403;
}
}
map $geoip2_country_code $blocked_country {
default 0;
RU 1;
CN 1;
}
server {
error_page 403 /geo-blocked.html;
location = /geo-blocked.html {
internal;
root /var/www/error-pages;
}
if ($blocked_country) {
return 403;
}
}
Reload NGINX:
nginx -t && systemctl reload nginx
Testing
# Test with a known IP
curl -H 'X-Forwarded-For: 8.8.8.8' https://example.com
# Should work (Google DNS - US)
curl -H 'X-Forwarded-For: 77.88.8.8' https://example.com
# Should be blocked (Yandex DNS - Russia, if RU is blocked)
Testing Locally
Local/private IPs return empty country codes. Test with real public IPs.
Advanced Usage
Use Real Client IP Behind Proxy/CDN
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
$geoip2_country_code source=$http_x_forwarded_for country iso_code;
}
Different Rules for Different Paths
# Block everywhere except API
location / {
if ($blocked_country) {
return 403;
}
# ... normal config ...
}
location /api/ {
# API accessible from anywhere
# ... api config ...
}
Log Country Information
log_format geo '$remote_addr - $geoip2_country_code - $request';
access_log /var/log/nginx/geo.log geo;
Rate Limit by Country
# Stricter limits for high-risk countries
map $geoip2_country_code $limit_key {
default $binary_remote_addr;
RU $binary_remote_addr$geoip2_country_code;
CN $binary_remote_addr$geoip2_country_code;
}
limit_req_zone $limit_key zone=geo_limit:10m rate=10r/s;
Common Country Codes
| Code | Country | Code | Country |
|---|---|---|---|
| US | United States | DE | Germany |
| GB | United Kingdom | FR | France |
| CA | Canada | AU | Australia |
| CN | China | RU | Russia |
| IN | India | BR | Brazil |
| JP | Japan | KR | South Korea |
| KP | North Korea | IR | Iran |
Full list: ISO 3166-1 alpha-2
Troubleshooting
Country always empty
- Check database path exists:
ls -la /usr/share/GeoIP/ - Verify module loaded:
nginx -V 2>&1 | grep geoip2 - Check IP isn't private/localhost
Wrong country detected
- Update database:
geoipupdate - Check if behind CDN/proxy (use
X-Forwarded-For) - MaxMind accuracy: ~99.8% for countries
Database not updating
- Check timer:
systemctl status geoipupdate.timer - Verify credentials in
/etc/GeoIP.conf - Run manually:
geoipupdate -v
Related
-
GeoIP2 Module
Complete directive reference
-
ModSecurity WAF
Full web application firewall
-
Rate Limiting
Protect against abuse