Block access from country by IP in Apache
In this blog I will show how you can block access to your Apache hosted internet services, forbidding access to a whole country. The access is blocked based on the IP address of a client. In case of a VPN where the user connects to a VPN server in another country, the user will still be able to access the site.
The internet is a great to ensure freedom of speech. Anyone can raise his/her voice; use the information to be informed on what is happening in the world, let others know about something, share knowledge. You can do so by using a social site or by hosting your own site. The ease of access to information; be able to search it instantly; have huge amount of information able to be discovered by a large number of the world population. This is one of the true great contributions to really make the world a better place. Some countries don’t like this, applying censorship, access restriction, or worse. And basically, if you decide to block a country to access your site, it’s one step to the wrong direction.
Why would you block a whole country? Isn’t a great thing about the internet that it’s accessible from anywhere in the world, just using a browser? It’s not as simple. A few reasons to block a country can be:
- Legal requirements. Your site is not in compliance with the countries law. For instance, maybe you are logging too much personal information?
- The functionality is not meant for that country. You have a commercial service, and are not offering a payment option or a localized version.
- You are popular in a country and flooded with a lot of requests, but these are just operational overhead for you as your site is not targeted for these users.
- If you think hard enough, you can come up with a good reason.
After finding yourself in the situation to block a specific country, the question is: HOW? You can use a blocker in your web platform (WordPress plugin), or use Apache to do so. Using a .htpasswd file for this is not optimal due to performance. Better is to use a module. A quick Google search reveals that a good option is to use the GeoLite DB from MaxMind. And they also offer an Apache 2.4 module. The module works with Apache 2 and the HTTPD server available on Amazon AMI images.
Some references to projects used to set the country blocking up.
- Libmaxmind db https://github.com/maxmind/libmaxminddb
- Apache module https://github.com/maxmind/mod_maxminddb
- GeoLite 2 DB http://dev.maxmind.com/geoip/geoip2/geolite2/
Steps for using GeoLite2 DB for blocking countries in Apache
- Download GeoLite 2 DB
- Install dependencies
- Install Apache module
1. Download GeoLite2 database
The GeoLite2 DB is available as a free and commercial license. The free version should be good enough for a private blog. You can get the free version from MaxMind site.
Select GeoLite 2 Country and binary format. Download the file using wget.
Unzip the file.
tar zxvf GeoLite2-Country.tar.gz
The actual DB file is close to 3 MB in size.
Copy it to a directory were the apache users can find it. A good default location is /usr/local/share in a new directory named GeoIP.
sudo mkdir /usr/local/share/GeoIP sudo cp /home/ec2-user/geolite2db/GeoLite2-Country_20170704/GeoLite2-Country.mmdb /usr/local/share/GeoIP/
2. Install dependencies
For the Apache module to work, the C library libmaxmind must be installed. This can be done by using yum.
sudo yum install libmaxminddb.x86_64 libmaxminddb-devel.x86_64
HTTPD devel files
Another dependency is the HTTP development files. These can also easily installed using yum.
sudo yum install httpd24-devel.x86_64
3. Install Apache module
The Apache module is available as source code from GitHub. For installation, download the latest release from GitHub. In my case, the latest release was version 1.1.0. Download the tar file.
Download the release to Linux using wgetand unzip it.
tar zxvf mod_maxminddb-1.1.0.tar.gz
Now you can compile and install the module. To do so, run
./configure sudo make install
This should compile and put the files correctly into the right directory of HTTPD. If an error occurs during configuration, compilation or installation, look at the error message and good luck.
The directive to load the new module was automatically added to the file /etc/httpd/conf/httpd.conf
To test that the module can be loaded, restart HTTPD.
sudo service httpd restart
The service needs to start without error. This indicates that the module was successfully loaded. To validate this, check if the new module is actually loaded by HTTPD. To do so, list all loaded modules.
sudo httpd –M
Search for the maxmind module:
The new module is correctly loaded by HTTPD. Now we can configure Apache to make use of the module.
Edit the HTTP config file and add the directive to block a specific country. The GitHub site of MaxMind contains an example that serves as a very good starting point.
MaxMindDBEnable On MaxMindDBFile DB /usr/local/share/GeoIP/GeoLite2-Country.mmdb MaxMindDBEnv MM_COUNTRY_CODE DB/country/iso_code SetEnvIf MM_COUNTRY_CODE ^(RU|DE|FR) BlockCountry Deny from env=BlockCountry
Using the above example, let’s adjust it to block Brazil. No worry, I won’t block Brazil, this is just a test as my IP currently is from Brazil, making it easier for me to test the setup. To block Brazil, check if MM_COUNTRY_CODE starts with BR: SetEnvIf MM_COUNTRY_CODE ^(BR) BlockCountry
MaxMindDBEnable On MaxMindDBFile DB /usr/local/share/GeoIP/GeoLite2-Country.mmdb MaxMindDBEnv MM_COUNTRY_CODE DB/country/iso_code SetEnvIf MM_COUNTRY_CODE ^(BR) BlockCountry Deny from env=BlockCountry
Add the above configuration snippet into a Location or Directory directive. This is because of the Deny command. This cannot be added directly under a virtual host.
<VirtualHost _default_:443> <Location /> MaxMindDBEnable On MaxMindDBFile DB /usr/local/share/GeoIP/GeoLite2-Country.mmdb MaxMindDBEnv MM_COUNTRY_CODE DB/country/iso_code SetEnvIf MM_COUNTRY_CODE ^(BR) BlockCountry Order deny,allow Allow from al1 Deny from env=BlockCountry </Location> </VirtualHost>
To activate the configuration and to block Brazil, a restart of HTTPD is needed.
sudo service httpd restart
After HTTPD is successfully restarted, the new configuration is activated. To see if it is working, a basic test is to just access the site from an IP address that is blocked.
My IP is from Brazil, accessing my site now should give me an access denied message.