How to Block All Traffic from a Specific Country (e.g., Philippines) Using GeoIP in PHP/Apache


1 views

Many web applications face persistent abuse from specific geographic regions. In my case, Philippine IP ranges were generating:

  • Carding attempts (testing stolen credit cards)
  • Spam account registrations
  • Automated vulnerability scanning
  • Referral spam from .ph domains

While security measures like rate limiting and CAPTCHAs help, they don't address the root issue when:

  • 90%+ of malicious traffic originates from one country
  • Legitimate users from that region are non-existent
  • The traffic consumes significant server resources

Here are three practical approaches to implement country blocking:

Option 1: MaxMind GeoIP with PHP (Recommended)

The most accurate solution using MaxMind's free GeoLite2 database:


// Download the GeoLite2 database from:
// https://dev.maxmind.com/geoip/geolite2-free-geolocation-data

require_once 'vendor/autoload.php';
use MaxMind\Db\Reader;

$ip = $_SERVER['REMOTE_ADDR'];
$reader = new Reader('/path/to/GeoLite2-Country.mmdb');

try {
    $record = $reader->get($ip);
    if ($record && $record['country']['iso_code'] === 'PH') {
        header('HTTP/1.1 403 Forbidden');
        exit('Access from your region is not permitted');
    }
} finally {
    $reader->close();
}

Option 2: Apache .htaccess Blocking

For simpler implementations using IP ranges:


# Download Philippine IP ranges from:
# https://www.ipdeny.com/ipblocks/

# Add to your .htaccess
Order Allow,Deny
Allow from all
Deny from 1.0.0.0/21
Deny from 1.20.0.0/16
# ... (add all PH IP ranges)

Option 3: Cloudflare Firewall Rules

If using Cloudflare, create a firewall rule:


# In Cloudflare Dashboard:
# Security → WAF → Firewall Rules
# Create rule with expression:
# (ip.geoip.country eq "PH") 
# Action: Block

When implementing country blocking:

  • MaxMind DB adds ~0.5ms lookup time (negligible for most apps)
  • .htaccess becomes slow with 500+ IP ranges
  • Cloudflare adds zero server overhead
  • Update GeoIP databases monthly (they change constantly)
  • Monitor false positives in server logs
  • Consider whitelisting known-good IPs that might be misclassified

Like many web developers, I've noticed an alarming pattern - while legitimate users from the Philippines are virtually nonexistent on my platform, malicious traffic from PH IP ranges continues to flood my servers. Common attack patterns include:

  • Card testing attempts (200-300 requests/minute)
  • Credential stuffing attacks
  • Google.ph referrals leading to scraping bots

While blanket country blocking isn't ideal, the signal-to-noise ratio from Philippine IPs makes this a justified exception:

// Sample log analysis showing PH traffic patterns
2023-11-15 03:22:11 | 112.206.xxx.xxx (PH) | POST /api/payment | 403 Forbidden
2023-11-15 03:22:12 | 120.28.xxx.xxx (PH) | GET /login | 401 Unauthorized
2023-11-15 03:22:13 | 110.54.xxx.xxx (PH) | POST /register | 400 Bad Request

Option 1: Apache .htaccess Method

The most performant solution for Apache users:

# Block Philippines IP ranges
<IfModule mod_geoip.c>
    GeoIPEnable On
    SetEnvIf GEOIP_COUNTRY_CODE PH BlockCountry
    Deny from env=BlockCountry
</IfModule>

# Fallback using MaxMind data if GeoIP module unavailable
<IfModule !mod_geoip.c>
    # PH IP ranges (updated Q4 2023)
    Deny from 110.54.0.0/15
    Deny from 112.201.0.0/16
    Deny from 120.28.0.0/16
    # Add other PH CIDR blocks as needed
</IfModule>

Option 2: PHP Middleware Approach

For more flexibility in PHP applications:

// geo_block.php
require_once 'vendor/autoload.php';
use GeoIp2\Database\Reader;

$reader = new Reader('/usr/local/share/GeoIP/GeoLite2-Country.mmdb');
try {
    $record = $reader->country($_SERVER['REMOTE_ADDR']);
    if ($record->country->isoCode === 'PH') {
        http_response_code(403);
        exit('Access from your region is restricted');
    }
} catch (Exception $e) {
    // Fail open rather than block legitimate traffic
    error_log("GeoIP error: ".$e->getMessage());
}

Keep your IP ranges current using these strategies:

  • Subscribe to PH NIC updates (https://www.phnic.net.ph/)
  • Set up a monthly cron job to refresh MaxMind databases
  • Monitor new ASNs allocated to Philippine providers

Example update script:

#!/bin/bash
wget -O /tmp/GeoLite2-Country.tar.gz "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=YOUR_KEY&suffix=tar.gz"
tar -xzf /tmp/GeoLite2-Country.tar.gz -C /tmp
mv /tmp/GeoLite2-Country_*/GeoLite2-Country.mmdb /usr/local/share/GeoIP/

For those wanting more nuanced control:

// Hybrid approach combining GeoIP with rate limiting
$redis = new Redis();
$key = "ph_ip:".$_SERVER['REMOTE_ADDR'];
if ($redis->incr($key) > 10) {
    header('HTTP/1.1 429 Too Many Requests');
    exit;
}
$redis->expire($key, 3600);