Use GeoIP and htaccess to deny countries access to your website

October 19, 2016 by Pat - Comments - 3 min read

O'Brien LabsI run about a dozen websites, and one of them switched over to the XenForo forum software. The problem with forums is once the spambots find it, they’re registering like crazy. My best efforts to use CAPTCHA didn’t work well. Then I added a question which uses AJAX to verify the answer against an external API. That helped but they were still able to figure out a valid answer. They then were manually verifying the registration via email. My best efforts to stop them really only slowed them down. I wanted it to end.

Using a self-hosted Piwik analytics instance I was able to determine that most of the spammers came from India and China. I could have added those two countries known IPs to my firewall, but that’s a lot of overhead. Probably would have been around 8,000 entries. That would have to be updated all the time.

Instead I decided to use Maxmind’s GeoIP database (the free versions), Apache mod_geoip and .htaccess to deny those countries. Sure – denying countries means I’m blocking my content to people who aren’t spammers, but my content isn’t translated to these countries, nor does my SEO target them. So I’m OK with this – your mileage may vary.

I’m running on CentOS 7, and here’s the steps I took to get it going

  1. Install the GeoIP packages and the Apache httpd mod_geoip module: yum install GeoIP GeoIP-devel GeoIP-data zlib-devel mod_geoip

  2. Update the httpd geoip conf as below, which adds in a 2nd database which contains City information: nano /etc/httpd/conf.d/geoip.conf

<IfModule mod_geoip.c>
 GeoIPEnable On
 GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
 GeoIPDBFile /usr/share/GeoIP/GeoIPCity.dat
</IfModule>
  1. Create this bash script which will download the databases. nano /root/geoip_updater.sh
#!/bin/bash
#Download Maxmind GeoIP databases

cd /usr/share/GeoIP
mv GeoIP.dat GeoIP.dat.old
mv GeoIPCity.dat GeoIPCity.dat.old

/bin/wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
/bin/wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz

gunzip GeoIP.dat.gz
gunzip GeoLiteCity.dat.gz

mv GeoLiteCity.dat GeoIPCity.dat
  1. Make it executable: chmod +x /root/geoip_updater.sh

  2. Run the script to get a fresh copy of both databases: ./root/geoip_updater.sh

  3. Restart Apache httpd to load in the new database and module settings: sudo systemctl httpd restart

7. Add a crontab entry to automatically download new databases every month. crontab -e

# GeoIP Updater every 1st day of the month
@monthly /root/geoip_updater.sh > /dev/null 2>&1

8. Open up your site’s .htaccess and add the following:

# Block Countries using GeoIP and mod_geoip
SetEnvIf GEOIP_COUNTRY_CODE IN BlockCountry
SetEnvIf GEOIP_COUNTRY_CODE CN BlockCountry
SetEnvIf GEOIP_COUNTRY_CODE RU BlockCountry
Deny from env=BlockCountry

This will block India, China and Russia. You can add more countries to the list as you need, just use their 2 character country code. You can get a list of the country codes here: https://countrycode.org/

That’s it! I’ve seen a dramatic drop in spambot registrations after doing this.

Hopefully this helps someone – or at the very least reminds me how to do this again in the future.

Share this post:

About Pat

I'm a I.T. systems engineer by day and in my spare time I code. I've made WordPress websites and plugins, weewx extensions and static html sites using Jekyll. I'm a technologist at heart and I enjoy tinkering on many different technology projects. Here on my site you will find some of the projects I've worked on, and other random bits of knowledge that I hope help someone along the way.

mentions