Blocking country spam using Apache and mod_geoip2

Ketola

Member
Our forums are getting decent amounts of spam from specific countries that rarely see visits from genuine users. Therefore I decided to block them all from posting by employing mod_geoip2 and GeoLite Country database. Thought I'd share the process in case someone else is dealing with a similar issue.

This process is for CentOS, so please adjust accordinly for your distro. GeoIP-devel is installed from EPEL.
  1. Install GeoIP and development headers and libraries
    Code:
    yum -y install GeoIP-devel httpd-devel
  2. Download and compile mod_geoip2
    Code:
    cd /tmp
    wget --no-check-certificate "https://github.com/maxmind/geoip-api-mod_geoip2/archive/1.2.10.tar.gz" -O geoip-api-mod_geoip2-1.2.10.tar.gz
    tar xvfz geoip-api-mod_geoip2-1.2.10.tar.gz && rm -f geoip-api-mod_geoip2-1.2.10.tar.gz
    cd geoip-api-mod_geoip2-1.2.10/
    apxs -i -a -L/usr/local/lib -I/usr/local/include -lGeoIP -c mod_geoip.c
  3. Configure GeoIP to use GeoLite Country db (506)
    Code:
    cat <<EOF >/etc/GeoIP.conf
    
    LicenseKey YOUR_LICENSE_KEY_HERE
    UserId YOUR_USER_ID_HERE
    ProductIds 506
    EOF

  4. Update the DB and setup a weekly cron to keep it up to date
    Code:
    geoipupdate
    
    cat <<EOF >/etc/cron.weekly/geoipupdate
    #!/bin/sh
    /usr/bin/geoipupdate >/dev/null 2>&1
    EOF
    
    chmod 755 /etc/cron.weekly/geoipupdate
  5. Setup Apache to use the GeoLite Country DB, disable mod_geoip by default
    Code:
    cat <<EOF >/etc/httpd/conf.d/geoip.conf
    
    <IfModule mod_geoip.c>
      GeoIPEnable Off
      GeoIPDBFile /usr/share/GeoIP/GeoLiteCountry.dat
    </IfModule>
    EOF
  6. Add the following to XenForo .htaccess file (or your VirtualHost)
    Code:
    #   If GeoIP module is loaded use it to block users from specified geos
    
    <IfModule mod_geoip.c>
        GeoIPEnable On
        # ISO 3166 country codes for blocked geos. See http://dev.maxmind.com/geoip/legacy/codes/iso3166/
        RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^(PK|IN|CN|BD)$
        # Match on query string when testing under VirtualHost
        RewriteCond %{QUERY_STRING} ^.*(create-thread|quick-update|add-reply).*$ [OR]
        # Match on request URI when testing under .htaccess
        RewriteCond %{REQUEST_URI} ^.*(create-thread|quick-update|add-reply).*$
        RewriteRule .* - [F]
    </IfModule>
  7. Restart Apache to enable mod_geoip
    Code:
    apachectl graceful
That's it! Visitors from blocked countries (in this example Pakistan, India, China, Bangladesh) are allowed to browse the forums and even sign up for an account, but they cannot post new threads or reply to existing ones. Changing the way the bans work can be done by simply adjusting the rewrite conditionals. You could, for example, block all POST requests instead to make the site completely read-only for the users.
 
And usually will degrade your Server Performance.
I haven't measured the effect on performance (server load, increased latency), but I'd say it's negligible considering the gains. The GeoIP db itself is small (less than 800k) and will always be in memory. IP lookups against it are rather quick.

Of course if you're concerned about the performance of mod_geoip you could always switch to enabling GeoIP only for specific URLs.

Here are the stacked load averages for our web backends after enabling mod_geoip on April 29th (the spikes are from sending out newsletters):
stacked-load.webp
 
You could use CloudFlare to block countries too, if you're using CloudFlare. They have an option for this.
 
Top Bottom