Problem: I have a multi-site Apache web-server, hosting localised copies of the site for many countries. I would like customer visiting the site to be automatically re-directed to their country specific site. Something similar to google, where if you visit www.google.com you will be re-directed to country specific site in my case it is www.google.co.uk
Solution: As the heading says, I will be using GeoIP module from MaxMind to achieve the solution. GeoIP module comes in two flavours free and paid, difference apart from the price is the data file accuracy. The explanations and procedure explained here works for both flavours of GeoIP. I’m using free version of the module and the setup is on Debian stable as that’s my Linux of choice. All steps shown below will work on any other versions of Linux as long as you make the configuration changes in the right files. I will try and point out the differences as they come along.
Technically this is what happens, when a request comes to the Apache web-server; GeoIP module kicks in and sets few Apache environment variables based on requests REMOTE_ADDR field. The set variables are in-turn used by rewrite module to decide on the site the user should be redirected too.
I assume you have a working instance of Apache web-server with rewrite module and be able to access the site from outside your network, or in other words reachable on the Internet. Note: It doesn’t matter if Apache is running on different port.
Step1. Install GeoIP module, Debian packages this module by default use below command to install it
$ sudo apt-get install libapache2-mod-geoip
If you are using RedHat or CentOS, you might have to compile the module, as there are no binary packages. Download the latest package from here, assuming you downloaded the file mod_geoip2_1.2.7.tar.gz, follow this steps from the download folder.
$ tar zxf mod_geoip2_1.2.7.tar.gz
$ cd mod_geoip2_1.2.7
$ apxs -i -a -L /usr/local/lib -I /usr/local/include -l GeoIP -c mod_geoip.c
Last command compiles and installs the module.
If you have just setup the RedHat or CentOS box you might have to install this dependencies httpd-devel.x86_64, gcc.x86_64, zlib-devel.x86_64, make.x86_64, wget.x86_64 before you compile.
If you get a error during apxs compile check you have GeoIP’s C API installed. If not download it from here. Read the INSTALL file before compiling and installing the C API’s. Usually its just this three commands
$ ./configure && make && make install
To successfully complete this step restart Apache and check GeoIP module is loaded. This is done with following command
$ sudo apachectl -t -D [DUMP_MODULES] | grep geo
geoip_module (shared)
Syntax OK
If you get a response like the one above then you are though this step.
On RedHat or CentOS you have to use full path to apachectl command
Step2. Setup Named virtual host. There is quite a few difference between the way Debian manages Apache configuration files to that of RedHat. I’m assuming that you know how to setup NameVirtualHost on RedHat, as I will be only showing the Debian side of things.
Create a three folders under /var/www/ like uk, us and fr, and in each create a index.html file with following content
<html>
<body>
<h1>XX Site</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body>
</html>
Replace ‘XX’ with country name
Create three files named uk_site, us_site, fr_site under /etc/apache2/sites-available with following content
ServerAdmin webmaster@localhost
DocumentRoot /var/www/xx
ServerName xx.website.com
# mod_rewrite options
RewriteEngine On
RewriteOptions Inherit
ErrorLog logs/xx-website-error_log
CustomLog logs/xx-website-access_log
Replace xx with site specific code, i.e. either of uk, us or fr
Enable above created site configurations and restarts Apache server
$ sudo a2dissite default
$ sudo a2ensite uk_site us_site fr_site
$ sudo apachectl restart
First command disables existing default site. Once Apache is restarted, test if you can see all the three site. You might have to add ServerName values to your hosts file corresponding to Apache server’s local IP address. If you can access all the three sites you have successfully completed this step.
Step3. As all the required setup is complete lets configure GeoIP module. Download the latest binary data file containing the IP ranges from here, extract it and move it to a know location. Create a file geoip-rewrite.conf under /etc/apache2/ directory with following content.
GeoIPEnable On
GeoIPDBFile /etc/apache2/geoip/GeoIP.dat
RewriteEngine On
#Variable to identify the source
SRC_EXTERNAL_ADDR=TRUE
# If accessing from private network allow access to all sites
SetEnvIf REMOTE_ADDR ^10\. SRC_EXTERNAL_ADDR=TRUE
SetEnvIf REMOTE_ADDR ^172\.[1-3]{1}\d{1}. SRC_EXTERNAL_ADDR=TRUE
SetEnvIf REMOTE_ADDR ^192\.168\. SRC_EXTERNAL_ADDR=TRUE
# You can append your external IP address here
# SetEnvIf REMOTE_ADDR xxx\.xx\.xx\.xx SRC_EXTERNAL_ADDR=TRUE
# UK Site rewrite
RewriteCond %{ENV:SRC_EXTERNAL_ADDR} !^TRUE$
RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^GB$
RewriteCond %{HTTP_HOST} !^uk.website.com [NC]
RewriteRule ^(.*)$ http://uk.website.com$1 [L]
# US Site rewrite
RewriteCond %{ENV:SRC_EXTERNAL_ADDR} !^TRUE$
RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^US$
RewriteCond %{HTTP_HOST} !^us.website.com [NC]
RewriteRule ^(.*)$ http://us.website.com$1 [L]
# French Site rewrite
RewriteCond %{ENV:SRC_EXTERNAL_ADDR} !^TRUE$
RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^FR$
RewriteCond %{HTTP_HOST} !^fr.website.com [NC]
RewriteRule ^(.*)$ http://fr.website.com$1 [L]
Add geoip-rewrite.conf to httpd.conf under /etc/apache2/ directory
If httpd.conf file is not present create one.
Restart Apache and try and access all site locally. If that works you are done with this step.
Step4. Testing with country specific IP address. This is easy to do if your browser of choice has some sort of extension to allow you to switch proxies. If you are a Google Chrome user as I do ProxySwitchy offers this functionality, If you use Firefox user check FoxyProxy. Install the extension in your browser check for country specific web proxies online, key that in to your extension and try accessing the three sites we put-up earlier. Based on the IP address you are coming from you will be directed to the right country site.
If you have added Apache web-server local address in hosts file replace the local IP of the Apache web-server with its external IP address. You still have to keep ServerName names unless those names are registered in your local or external DNS.