How to Install Mod_GeoIP for Apache in RHEL and CentOS

Mod_GeoIP is an Apache module that can be used to get the geographic location of the IP address of the visitor into the Apache webserver. This module allows you to determine the visitor’s country, organization, and location. It is especially useful for Geo Ad Serving, Target Content, Spam Fighting, Fraud Detection, Redirecting/Blocking visitors based on their country and much more.

GeoIP module allows system administrators to redirect or block web traffic according to the client’s geographical location. The geographical location is learned via the client IP address.

Mod_GeoIP has two different versions one is Free and another one is Paid and uses MaxMind GeoIP / GeoCity databases.

  1. Free Version: In the Free version, the Geo City and Country databases are available with 99.5% accuracy.
  2. Paid Version: In the Paid version, you will get both databases with 99.8% accuracy with some more advanced details about IP address.

If you like to check out the more differences between the Free and Paid version, please visit Maxmind.com.

This article explains how to set up and install the Mod_GeoIP module for Apache in RHEL and CentOS using the EPEL repository with YUM package manager utility.

We assume that you already have running RHEL and CentOS system with a working LAMP (Linux, Apache, MySQL, and PHP) setup. If not, then read our articles where we’ve shown the installation of both operating systems with LAMP.

Installation Of RHEL/CentOS
  1. Installation of RHEL 7 and CentOS 7 Minimal.
  2. Installation of RHEL 8 and CentOS 8 Minimal.
LAMP Setup on RHEL/CentOS
  1. How to Install LAMP (Linux, Apache, MySQL, PHP) on RHEL and CentOS 7
  2. How to Install Apache, MySQL/MariaDB, and PHP on RHEL and CentOS 8

Enable EPEL Repository in RHEL and CentOS

By default mod_Geoip is not available under RHEL / CentOS official repository, so we need to install and enable third party EPEL repository.

# yum install epel-release
# yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm  [On RHEL 8]

Install Mod_GeoIP in RHEL and CentOS

Once you’ve EPEL repository enabled on your system, you can simply install mod_geoip by running following command with their dependency packages.

# yum install mod_geoip GeoIP GeoIP-devel GeoIP-data zlib-devel

Download latest Geo City and Country Database

It’s a good idea to download the latest Geo City and Country Database to stay updated.

# cd /usr/share/GeoIP/
# mv GeoIP.dat GeoIP.dat_org
# wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz
# wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz
# gunzip GeoLite2-Country.tar.gz
# gunzip GeoLite2-City.tar.gz

Enable Mod_GeoIP in Apache

After the module has been installed, open and edit the module’s main configuration file, with a command-line text editor such as vi, and activate the module server-wide, as illustrated in the below excerpt.

# vi /etc/httpd/conf.d/geoip.conf

Set the line GeoIPEnable from Off to On. Also, make sure you add the absolute path to the GeoIP database file.

<IfModule mod_geoip.c>
GeoIPEnable On
GeoIPDBFile /usr/share/GeoIP/GeoIP.dat MemoryCache
</IfModule>

Restart the Apache service to reflect changes.

# systemctl restart httpd
OR
# service httpd restart

However, it’s not recommended to turn on the GeoIP module server-wide. You should enable the GeoIP module only in <Location> or <Directory> blocks where you would actually perform the traffic redirection or block.

Testing Mod_GeoIP Module

To test the mod_geoip module is working correctly with Apache, we need to create a PHP file called testgeoip.php under Apache root directory (e.g. /var/www/html).

# vi /var/www/html/testgeoip.php

Insert the following piece of php code to it.

<html>
<head>
  <title>What is my IP address - determine or retrieve my IP address</title>
 </head>
<body>
 <?php
     if (getenv(HTTP_X_FORWARDED_FOR)) {
        $pipaddress = getenv(HTTP_X_FORWARDED_FOR);
        $ipaddress = getenv(REMOTE_ADDR);
        echo "Your Proxy IP address is : ".$pipaddress. " (via $ipaddress) " ;
    } else {
        $ipaddress = getenv(REMOTE_ADDR);
        echo "Your IP address is : $ipaddress";
    }
    $country = getenv(GEOIP_COUNTRY_NAME);
    $country_code = getenv(GEOIP_COUNTRY_CODE);
    echo "<br/>Your country : $country ( $country_code ) ";
?>
</body>
</html>

Now, try to call the file using a web browser (e.g. http://localhost/testgeoip.php). You will get your IP address and Country details.

Updating GeoIP Database

GeoIP database is updated beginning of every month. So, it is very important to keep the GeoIP database up-to-date. To download the latest version of the database use the following command.

# cd /usr/share/GeoIP/
# mv GeoIP.dat GeoIP.dat_org
# wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz
# wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz
# gunzip GeoLite2-Country.tar.gz
# gunzip GeoLite2-City.tar.gz

Automatic GeoIP Database Update

We have written a small shell script that will automatically download the latest version of the GeoIP database every month. Just place any of the following script under /etc/cron.monthly.

Script 1
# Automatic GeoIP Database Update
#!/bin/sh
cd /usr/share/GeoIP
mv GeoIP.dat GeoIP.dat_org
wget -q http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz
gzip -d -f GeoLite2-Country.tar.gz
Script 2
#!/bin/sh

GEOIP_MIRROR="http://geolite.maxmind.com/download/geoip/database"
GEOIPDIR=/usr/share/GeoIP
TMPDIR=

DATABASES="GeoLiteCity GeoLiteCountry/GeoIP asnum/GeoIPASNum GeoIPv6"

if [ -d "${GEOIPDIR}" ]; then
        cd $GEOIPDIR
        if [ -n "${DATABASES}" ]; then
                TMPDIR=$(mktemp -d geoipupdate.XXXXXXXXXX)

                echo "Updating GeoIP databases..."

                for db in $DATABASES; do
                        fname=$(basename $db)

                        wget --no-verbose -t 3 -T 60 "${GEOIP_MIRROR}/${db}.dat.gz" -O "${TMPDIR}/${fname}.dat.gz"
                        gunzip -fdc "${TMPDIR}/${fname}.dat.gz" > "${TMPDIR}/${fname}.dat"
                        mv "${TMPDIR}/${fname}.dat" "${GEOIPDIR}/${fname}.dat"
                        chmod 0644 "${GEOIPDIR}/${fname}.dat"
                done
                [ -d "${TMPDIR}" ] && rm -rf $TMPDIR
        fi
fi

Redirecting Users based on Country

The below example code will redirect users based on the country code that we set to AS (Asia). This way you can redirect any users based on their county code.

GeoIPEnable On
GeoIPDBFile /usr/share/GeoIP/GeoIP.dat

# Redirect one country
RewriteEngine on
RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^AS$
RewriteRule ^(.*)$ https://www.tecmint.com$1 [R,L]

Blocking Users based on Country

This example will block users based on the country code that GeoIP sets. The below example will block users from AS (Asia) and US (United States) countries.

GeoIPEnable On
GeoIPDBFile /usr/share/GeoIP/GeoIP.dat

SetEnvIf GEOIP_COUNTRY_CODE AS BlockCountry
SetEnvIf GEOIP_COUNTRY_CODE US BlockCountry
# ... place more countries here

Deny from env=BlockCountry

Allowing Users based on Country

This below example will only allow users from below mentioned countries.

GeoIPEnable On
GeoIPDBFile /usr/share/GeoIP/GeoIP.dat

SetEnvIf GEOIP_COUNTRY_CODE AS AllowCountry
SetEnvIf GEOIP_COUNTRY_CODE US AllowCountry
# ... place more countries here

Deny from all
Allow from env=AllowCountry

For more information about mod_geoip and its usage can be found at http://www.maxmind.com/app/mod_geoip. If you’re having any trouble in setting up a mod_geoip module, please let us know via comments and please don’t forget to share it with your friends.

Hey TecMint readers,

Exciting news! Every month, our top blog commenters will have the chance to win fantastic rewards, like free Linux eBooks such as RHCE, RHCSA, LFCS, Learn Linux, and Awk, each worth $20!

Learn more about the contest and stand a chance to win by sharing your thoughts below!

Ravi Saive
I am an experienced GNU/Linux expert and a full-stack software developer with over a decade in the field of Linux and Open Source technologies

Each tutorial at TecMint is created by a team of experienced Linux system administrators so that it meets our high-quality standards.

Join the TecMint Weekly Newsletter (More Than 156,129 Linux Enthusiasts Have Subscribed)
Was this article helpful? Please add a comment or buy me a coffee to show your appreciation.

34 Comments

Leave a Reply
  1. Hi,

    There is no mod_geoip in EPEL for CentOS/RHEL8. You’ll need to add raven repo (pkgs.dyn.su) and then do:

    # yum --enablerepo=raven-extras install mod_geoip
    
    Reply
  2. domain geolite.maxmind.com unreachable 404 error

     wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz
    --2020-10-07 12:48:42--  http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz
    Risoluzione di geolite.maxmind.com (geolite.maxmind.com)... fallito: Nome o servizio sconosciuto.
    wget: impossibile risolvere l'indirizzo dell'host "geolite.maxmind.com"
    
    Reply
  3. Greets, nice article, but a bit out of date now.

    I see mod_geoip is no longer provided by EPEL. Any idea where else it can be found?

    Thanks

    Reply
  4. I’m getting the following error when trying to use script 2 for the cron:

    Updating GeoIP databases...
    http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz:
    2019-10-23 13:30:41 ERROR 404: Not Found.
    http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz:
    2019-10-23 13:30:41 ERROR 404: Not Found.
    http://geolite.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz:
    2019-10-23 13:30:41 ERROR 404: Not Found.
    http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz:
    2019-10-23 13:30:41 ERROR 404: Not Found.
    

    Any ideas where these have been moved to?

    Reply
  5. You changed to the file name in this line: gunzip GeoLite2-Country.tar.gz
    but that just produces a .tar file in a new directory.

    It no longer produces the file: GeoIP.dat nor does it put it in the current directory
    so the lines in later code: GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
    will no longer work.

    More changes are needed in your code. Have you tested your code? I don’t think it will work with all the changes MaxMiind has made in their system.

    Reply
    • @Richard,

      Thanks for your input, I think I should re-install and test it again Mod_GeoIP, give me a day or two to test and update this article with latest information.

      Reply
  6. Hello,

    deny on geopip.conf does not work. I get the error:

    Stopping httpd: [ OK ]
    Starting httpd: Syntax error on line 21 of /etc/httpd/conf.d/geoip.conf:
    deny not allowed here

    i used the syntax:

    SetEnvIf GEOIP_COUNTRY_CODE DE AllowCountry
    SetEnvIf GEOIP_COUNTRY_CODE AT AllowCountry

    Deny from all
    Allow from env=AllowCountry

    How can i fix this?

    Thanks!

    Reply
  7. Hi there, nice article.
    But how can I block countries for all my domains which are hosted on my server.
    Or should I have to paste the code into each .htaccess for each domain?

    Reply
    • Yes, you must create a specific .htaccess file under each domain and add the following example of code to block countries.

      SetEnvIf GEOIP_COUNTRY_CODE CN BlockCountry
      SetEnvIf GEOIP_COUNTRY_CODE RU BlockCountry
      Deny from env=BlockCountry
      
      Reply
  8. Dear ALL

    Above post not correct

    good tutorial, after installation It should be like that for blocking country

    SetEnvIf GEOIP_COUNTRY_CODE CN BlockCountry=1
    SetEnvIf GEOIP_COUNTRY_CODE RU BlockCountry=1
    Deny from env=BlockCountry

    Thanks
    Rishipal singh
    Eliresearch.com

    Reply
  9. Dear ALL

    good tutorial, after installation It should be like that for blocking country

    SetEnvIf GEOIP_COUNTRY_CODE CN BlockCountry=1
    SetEnvIf GEOIP_COUNTRY_CODE RU BlockCountry=1
    Deny from env=BlockCountry

    Thanks
    Rishipal singh

    Reply
  10. resolved: You need to configure dynamic linker run time bindings as follows:
    # echo ‘/usr/local/lib’ > /etc/ld.so.conf.d/geoip.conf

    Run ldconfig to activate configuration:
    # ldconfig
    # ldconfig -v | less

    Reply
  11. Hi,
    Thank you for the tutorial,

    when I apply all the steps above, I can’t get the country, I only get the IP.
    I think there is some missing step for me.

    can you please help???

    Reply
  12. Hi,

    nice tutorial.
    I try u example and it show me the right land.
    But if i try to get the GEOIP_REGION or the CITY the result is empty.
    What reason could have. thanks for the help

    best regads
    michael

    Reply
  13. I don’t code in PHP but when I was testing testgeoip.php script it only worked after I changed:
    <?
    to
    <?php

    Thanks for this step by step guide it has been really helpful, it is almost up and running. My only issue is that I get an error after changing the httpd.conf to add the country restriction to the server:
    "deny not allowed here"

    Any help would be appreciated,

    Reply
    • Use “IfModule” section to add. Use this way.

      <IfModule mod_geoip.c>
      GeoIPEnable On
      GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
      
      SetEnvIf GEOIP_COUNTRY_CODE AS AllowCountry
      
      Deny from all
      Allow from env=AllowCountry
      
      # Now allow specific IPs
      # Allow from 172.16.25.126
      
      </IfModule>
      
      Reply
    • Thanks Rui for mentioning it here.
      Absolutely, this is the change we have to make to get the country be shown on the screen with this script.

      Reply

Got Something to Say? Join the Discussion...

Thank you for taking the time to share your thoughts with us. We appreciate your decision to leave a comment and value your contribution to the discussion. It's important to note that we moderate all comments in accordance with our comment policy to ensure a respectful and constructive conversation.

Rest assured that your email address will remain private and will not be published or shared with anyone. We prioritize the privacy and security of our users.