Security

IP Geolocation Blocking: Restrict Access by Country

May 19, 2026

Back to Blog
A modern alternative to cPanel, Plesk and CyberPanel — isolated, secure, AI-assisted.
Start free

Why Block Traffic by Country?

Not all traffic to your server is welcome. If your website serves customers exclusively in North America and Europe, there is little reason to accept SSH connections from countries where you have no users, employees, or business relationships. IP geolocation blocking — also called geo-blocking or geo-fencing — allows you to restrict access based on the geographic origin of an IP address.

The motivations for implementing geo-blocking fall into several categories:

Security

A significant percentage of brute force attacks, vulnerability scans, and spam originate from specific regions. Blocking these regions at the network level eliminates the traffic before it even reaches your application stack, conserving server resources and reducing log noise.

Compliance

Regulations like GDPR, OFAC sanctions, and data sovereignty laws may require restricting access from or to certain countries. Financial institutions, government contractors, and healthcare organizations often have strict geographic access requirements.

Content Licensing

Media companies, streaming services, and content distributors often need to restrict access based on licensing agreements that are territory-specific. While CDN-level blocking is more common for this use case, server-level enforcement serves as a backstop.

Attack Surface Reduction

If 95% of your legitimate traffic comes from 10 countries, blocking the remaining 185+ countries removes a massive amount of potential attack surface without affecting real users. This is the principle of least privilege applied to network access.

Important Caveat: Geo-blocking is NOT a security silver bullet. VPNs, proxies, Tor exit nodes, and compromised machines in "allowed" countries can bypass geographic restrictions. Think of geo-blocking as one layer in a defense-in-depth strategy, not a standalone solution.

GeoIP Databases: The Foundation

All geo-blocking implementations rely on IP-to-country databases. These databases map IP address ranges to geographic locations based on allocation data from Regional Internet Registries (RIRs) and other sources.

MaxMind GeoLite2

MaxMind's GeoLite2 is the most widely used free GeoIP database. It provides country-level accuracy of approximately 99.8% and city-level accuracy of around 75-80%. Since December 2019, downloading GeoLite2 requires a free account and license key.

# Install GeoIP update tool $ apt install geoipupdate # Configure with your license key $ cat /etc/GeoIP.conf AccountID 123456 LicenseKey YOUR_LICENSE_KEY EditionIDs GeoLite2-Country GeoLite2-City # Download/update databases $ geoipupdate Database GeoLite2-Country.mmdb updated Database GeoLite2-City.mmdb updated # Schedule weekly updates 0 4 * * 3 /usr/bin/geoipupdate
DatabaseCostAccuracy (Country)Update FrequencyFormat
MaxMind GeoLite2Free~99.8%Weekly.mmdb (binary)
MaxMind GeoIP2$100-3000/yr~99.9%3x/week.mmdb (binary)
IP2Location LiteFree~99.5%Monthly.BIN or CSV
DB-IP LiteFree~99%Monthly.mmdb or CSV

Method 1: Nginx GeoIP2 Module

The Nginx GeoIP2 module reads MaxMind's .mmdb database files and makes geographic information available as Nginx variables. This is the most efficient method for web traffic geo-blocking because it operates within the web server itself, without external dependencies.

Installation

# Install the module (Ubuntu/Debian) $ apt install libnginx-mod-http-geoip2 # Or compile from source with nginx $ git clone https://github.com/leev/ngx_http_geoip2_module.git $ ./configure --add-dynamic-module=/path/to/ngx_http_geoip2_module

Configuration

# nginx.conf — http {} block geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb { auto_reload 60m; $geoip2_data_country_code country iso_code; $geoip2_data_country_name country names en; } # Define allowed countries (allowlist approach) map $geoip2_data_country_code $allowed_country { default no; US yes; CA yes; GB yes; DE yes; FR yes; NL yes; AU yes; } # In server {} block — block non-allowed countries server { if ($allowed_country = no) { return 403; } # ... rest of server config }

Deny-List Approach (Block Specific Countries)

# Block specific countries instead of allowing specific ones map $geoip2_data_country_code $blocked_country { default no; CN yes; # China RU yes; # Russia KP yes; # North Korea IR yes; # Iran } server { if ($blocked_country = yes) { return 403; } }
Allow vs Deny — Which Approach? Use the allowlist approach if you know exactly which countries your users come from. Use the denylist approach if you want to block specific high-risk countries while allowing everyone else. The allowlist is more secure (blocks unknown countries by default), but the denylist is less likely to block legitimate users from unexpected locations.

Per-Location Geo-Blocking

You can apply geo-blocking to specific locations rather than the entire server. This is useful when you want to protect admin areas while leaving the public site accessible worldwide:

# Only geo-block the admin area location /wp-admin/ { if ($allowed_country = no) { return 403; } # ... proxy_pass or fastcgi_pass } # Public site remains accessible worldwide location / { # No geo restriction # ... proxy_pass or fastcgi_pass }

Method 2: nftables with IP Sets

For blocking traffic at the firewall level — before it reaches any application — nftables with IP sets is the most efficient approach. This blocks all traffic from specified countries, not just HTTP, which also protects SSH, FTP, email, and other services.

Incoming Packet
nftables Rule
IP set lookup
Match?
DROP / ACCEPT
# Download country IP ranges (use ipdeny.com or similar) $ wget https://www.ipdeny.com/ipblocks/data/aggregated/cn-aggregated.zone $ wget https://www.ipdeny.com/ipblocks/data/aggregated/ru-aggregated.zone # Create nftables set and populate $ nft add table inet filter $ nft add set inet filter geo_block '{ type ipv4_addr; flags interval; }' # Import IP ranges $ while IFS= read -r line; do nft add element inet filter geo_block "{ $line }" done < cn-aggregated.zone # Add drop rule $ nft add chain inet filter input '{ type filter hook input priority 0; }' $ nft add rule inet filter input ip saddr @geo_block drop
Performance Note: nftables IP sets use hash tables internally, so lookups are O(1) regardless of how many IP ranges are in the set. Even with hundreds of thousands of entries (China alone has ~8,000 CIDR blocks), the performance impact is negligible. This is far more efficient than individual iptables rules.

Method 3: Cloudflare Geo-Blocking (Free Tier)

If your domain uses Cloudflare as a CDN/proxy (even the free tier), you get access to powerful geo-blocking through their WAF rules. This is the easiest method to implement and requires zero server-side configuration.

1
Log into Cloudflare Dashboard and navigate to your domain.
2
Go to Security → WAF → Custom Rules (free tier allows 5 custom rules).
3
Create a rule with the expression builder: Field = "Country", Operator = "is in", Values = select countries to block. Action = "Block".
# Cloudflare WAF rule expression (API example) (ip.geoip.country in {"CN" "RU" "KP" "IR"}) # Or: allow only specific countries (not ip.geoip.country in {"US" "CA" "GB" "DE" "FR" "AU"}) # Protect only admin paths from non-local countries (http.request.uri.path contains "/wp-admin" and not ip.geoip.country in {"US" "CA"})

Cloudflare Advantages

  • Zero server load (blocking happens at edge)
  • Instant activation, no config reload
  • Free tier includes basic geo-blocking
  • Dashboard with visual analytics
  • Automatic GeoIP database updates

Cloudflare Limitations

  • Only protects HTTP/HTTPS traffic (not SSH, FTP, etc.)
  • Requires DNS to point through Cloudflare
  • Free tier limited to 5 WAF rules
  • Does not protect the origin IP directly
  • Adds slight latency (minimal with Anycast)

Method 4: Fail2ban with GeoIP

You can enhance Fail2ban to consider geographic information when making ban decisions. For example, failed SSH logins from allowed countries might get 3 retries, while attempts from blocked countries are banned on the first attempt.

# /etc/fail2ban/action.d/geoip-check.conf [Definition] actionban = COUNTRY=$(mmdblookup --file /usr/share/GeoIP/GeoLite2-Country.mmdb \ --ip <ip> country iso_code 2>/dev/null | grep -oP '"[A-Z]+"' | tr -d '"') if echo "CN RU KP IR" | grep -qw "$COUNTRY"; then nft add element inet filter blocked_ips "{ <ip> }" 2>/dev/null fi

Allow vs Deny: Choosing Your Strategy

StrategyBest ForRiskMaintenance
Allowlist (default deny)Services with known customer baseMay block unexpected legitimate usersAdd new countries as needed
Denylist (default allow)Public websites, blogs, SaaSDoes not block unknown threat sourcesAdd countries as threats emerge
Hybrid (per-service)Multi-service serversMore complex to managePer-service rule management

The hybrid approach is often the most practical. Allow worldwide access to your public website, restrict admin areas to your country, and allowlist SSH access to only your known office and home IPs:

# Hybrid approach in nginx server { # Public site - worldwide access location / { proxy_pass http://backend; } # Admin - country restricted location /admin { if ($allowed_country = no) { return 403; } proxy_pass http://backend; } # API - rate limited + country restricted location /api/ { if ($blocked_country = yes) { return 403; } limit_req zone=api burst=20 nodelay; proxy_pass http://backend; } }

VPN and Proxy Bypass: The Elephant in the Room

Any sophisticated attacker can bypass geo-blocking using VPNs, proxy servers, Tor, or cloud instances in allowed countries. This means geo-blocking should never be your only defense mechanism. Think of it as reducing noise and eliminating low-effort attacks, not as a foolproof barrier.

Defense in Depth: Geo-blocking reduces attack surface by 90%+ (blocking automated scanners and bots), but the remaining 10% of targeted attacks may use VPNs from allowed countries. Combine geo-blocking with strong authentication, rate limiting, WAF rules, and monitoring to create a comprehensive security posture.

Updating GeoIP Databases

IP-to-country mappings change as ISPs reallocate address blocks, new ranges are assigned, and organizations move. Running a stale GeoIP database leads to misclassification of legitimate users and missed blocks. Automate updates:

# Cron job to update GeoLite2 weekly and reload nginx 0 4 * * 3 /usr/bin/geoipupdate && /usr/sbin/nginx -s reload # For nftables IP sets, rebuild from fresh zone files 0 5 * * 1 /opt/scripts/update-geo-ipsets.sh

Legal Considerations

Before implementing geo-blocking, consider the legal implications:

GDPR (EU)

Blocking EU countries may actually help GDPR compliance if your site cannot comply with GDPR requirements. However, if you have EU users, blocking them could constitute discrimination. Consult legal counsel for your specific situation.

OFAC Sanctions

US companies are required to block access from sanctioned countries (currently including North Korea, Iran, Syria, Cuba, and Crimea region). Geo-blocking can help demonstrate compliance, though it is not considered sufficient on its own.

Performance Impact

Properly implemented, geo-blocking has minimal performance impact:

MethodLatency AddedMemory UsageCPU Impact
Nginx GeoIP2 module<0.1ms~50MB (loaded mmdb)Negligible
nftables IP sets<0.01ms~20-100MB (large sets)Negligible
Cloudflare0ms (edge)N/A (offloaded)None
Application-level (PHP/Python)1-5msVariesModerate
Best Practice: Always implement geo-blocking at the lowest possible level. Firewall (nftables) is the most efficient because it drops packets before they are processed. Nginx (GeoIP2 module) is the next best option. Application-level geo-blocking (in PHP, Python, etc.) is the least efficient because the full request is processed before the check occurs.

How Panelica Handles Geo-Blocking

Panelica includes IP blocking and firewall management through the panel interface. You can block individual IPs, entire CIDR ranges, and manage firewall rules without touching the command line. Combined with Cloudflare integration, you can implement geo-blocking rules with just a few clicks.

  • IP blocking management directly from the panel dashboard
  • nftables firewall rule management with an intuitive interface
  • Cloudflare integration for DNS management and edge-level blocking
  • Fail2ban with pre-configured jails for automated threat response
  • Real-time security logs showing blocked requests with geographic data

The combination of server-level firewall blocking (nftables), web server blocking (Nginx), and edge-level blocking (Cloudflare) gives you three independent layers of geographic access control. Even if one layer is bypassed, the others continue to enforce your policies.

Key Takeaways

IP geolocation blocking is a practical and effective tool for reducing your server's attack surface. It eliminates the vast majority of automated attacks, helps with regulatory compliance, and reduces log noise — all with negligible performance impact. The key is choosing the right implementation method for your needs: Cloudflare for simplicity, Nginx GeoIP2 for web traffic precision, and nftables for comprehensive protocol-level blocking.

Remember that geo-blocking is a complement to, not a replacement for, proper security practices. Combine it with strong authentication, rate limiting, intrusion detection, and regular security audits for a truly robust security posture. And always keep your GeoIP databases updated — stale data leads to both false positives (blocking legitimate users) and false negatives (missing actual threats).

Security-first hosting panel

Stop bolting tools onto a legacy panel.

Panelica is a modern, security-first hosting panel — isolated services, built-in Docker and AI-assisted management, with one-click migration from any panel.

Zero-downtime migration Fully isolated services Cancel anytime
Share:
When did you last test a restore?