Restricting access by IP address or geographic origin is a straightforward way to reduce exposure for admin panels, internal tools, or content with regional restrictions. This guide covers both approaches.
Basic IP Allow/Deny
location /admin {
allow 203.0.113.10;
allow 203.0.113.0/24;
deny all;
}
Rules are evaluated in order — the first matching rule applies; deny all at the end blocks everyone not explicitly allowed above it.
Allowing Multiple Specific IPs
location /admin {
allow 203.0.113.10;
allow 198.51.100.20;
allow 192.0.2.30;
deny all;
}
Blocking Specific IPs While Allowing Everyone Else
location / {
deny 203.0.113.50;
allow all;
}
Useful for blocking a known abusive IP while keeping the site otherwise publicly accessible.
Geolocation-Based Access Control
Requires the GeoIP2 module and a GeoIP database:
sudo apt install nginx-module-geoip2 -y
http {
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
$geoip2_data_country_code country iso_code;
}
map $geoip2_data_country_code $allowed_country {
default no;
US yes;
CA yes;
GB yes;
}
}
Applying the Geolocation Restriction
server {
if ($allowed_country = no) {
return 403;
}
}
Important Limitations of Geo-Blocking
IP-based geolocation isn't perfectly accurate and can be trivially bypassed with a VPN — appropriate as a coarse-grained content/compliance measure, not a robust security control on its own.
Combining IP Restriction with Basic Auth (Defense in Depth)
location /admin {
allow 203.0.113.10;
deny all;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
}
Layering both requires an attacker to both spoof/control an allowed IP AND know valid credentials — meaningfully stronger than either measure alone.
Using a Variable-Based Approach for More Complex Rules
geo $allowed_ip {
default 0;
203.0.113.0/24 1;
198.51.100.0/24 1;
}
server {
if ($allowed_ip = 0) {
return 403;
}
}
Useful when you have complex allow-list logic that would be unwieldy as many individual allow/deny lines.
Testing Your Configuration
curl -I https://yourdomain.com/admin
Test from both an allowed and a non-allowed source (or via a proxy/VPN simulating a different origin) to confirm the restriction is working correctly in both directions.
Common Errors
Legitimate access blocked unexpectedly — verify your actual current public IP (which may differ from what you assume, especially behind NAT or a dynamic IP) matches what's configured in the allow list.
Continue Reading
- How to Set Up Basic Authentication (htpasswd) in Nginx/Apache
- How to Rate Limit an API with Nginx
- How to Set Up a Bastion/Jump Host for Secure SSH Access
Browse more articles in Web Servers.