How to Block Entire Countries from Accessing Your Website


Trending posts on SitePoint today:


If you run a website, then by default it is accessible to the whole planet. Many websites are simply not relevant to people in other countries. So, you should not expect significant traffic from them as a matter of course.

If you have a local bookstore and your primary market is local people walking into your store, then there is no need to let any other countries index or waste bandwidth on your server. The same might be true of a carwash, or babysitters, or lawn mowing.

If you run a personal or even private website, such as a family blog, you may want to highly restrict traffic by default.

Here is a screenshot of Awstats telling me that China is responsible for the second-largest volume of traffic to a certain web forum I manage. This is just for January 2015.

Awstats China

While it is certainly possible that Chinese people may find the content of the forum useful, there is really no explanation for this activity. We don’t cater specifically for China or advertise to attract Chinese residents. The site does not even offer Chinese translation or speak to Chinese issues.

I also happen to know that 99% of all brute force user password hack attempts are from Chinese IP addresses. Approximately 50 to 100 brute force attempts at ‘guessing’ the passwords to legitimate user names comes from Chinese IP addresses every day on this site.

The difference between 1.9 million pages and 134,000 pages is pretty large, and 1.86GB of bandwidth is not the end of the world. But when I know that 99% of it is bogus, bots, brute force hacks, vulnerability scanners, and web crawlers, then why wouldn’t I just block China from accessing my site?

There are some reasons against blocking access to countries too. The obvious example are hotels. Even though they cater only to local people who walk in the door for a stay, foreigners traveling to the area will be searching for hotels before they get there. The same argument can be used for fancy restaurants, resorts, car rentals, commuter services and so on. You will have to decide (and check your web stats!) whether blocking particular countries will benefit you or not.

Below are many of the common ways to block countries, with some pros and cons and code samples.

.htaccess

If you are a web admin, you may know that trying to do some things (like block entire countries through .htaccess) is a losing game. Legit hackers use proxies or bot farms to do their dirty work. Just because an IP is from China, it doesn’t mean blocking that IP will do a lick of good in the long run.

Web admins will rarely block an IP simply because that IP did naughty things once. A real hacker would not use their own personal IP and there is no guarantee that the IP will always remain with an unscrupulous user.

Legitimate users might use proxies too! Be aware if you block a not-so-bad country just because you think they are irrelevant to your traffic, you may have users using proxies or VPNs in that country.

It is also a losing game because there are over four billion IPv4 IPs out there and no easy way to segregate them by country. In other words, your .htaccess or Apache config file (or other ACL/firewall) is likely to grow to hundreds of thousands of lines of text if you wanted to block countries yourself this way. It’s not practical, nor performant.

If you want to see how many lines it would take in .htaccess to block a country, try using ip2location. To block the US, you need over 150,000 lines of text!

The bottom line is this, do not use .htaccess or Apache config or any other web server ACL to try and block countries. It may be fine for a handful of IPs, but these files are read on every request and are not cached; it will hurt you eventually.

TIP: If you are interested in going the .htaccess route anyway, and want to get an accurate, ‘right from the source’, daily updated list of IPs by country, you might start by reading what this guy has done to automate things.

The actual code to block an IP using .htaccess can be as simple as this:

Order Deny,Allow
Deny from 1.1.1.1
Deny from 2.2.2.2
Deny from 3.3.3.3

You can generate code by using this tool.

You can get much more advanced, such as limiting based on what protocol is used, but this is the basic idea. Your .htaccess file would grow out of control!

Use a Hosting Company That Has Blocking as Part of Their Built-in Controls

This sounds nice, but is very rare. Most hosting companies provide servers in such a way as to make this a feature they cannot offer. The two main types are:

Bare Metal

A bare metal or VPS is a machine that you have complete control over. From software firewalls to hosting software and control panels, it’s all in your hands.

These might be a DigitalOcean Droplet or a bare metal server from InMotionHosting or Rackspace for example.

Often when you buy a bare metal or VPS, you do not get to change how the back end is routing. I have not found a host that has country blocking as part of its default plan and configuration. At best they give you a basic firewall for adding IPs to blacklists or whitelists.

Shared Hosting

You might get a server configured with Plesk control panel or cPanel. These are simply control panels for dealing with databases, emails, backups and many other things. A shared server typically comes with a control panel, but you can’t enable networking controls, which would then affect the other websites hosted on the shared server with the same IP.

At best, a control panel will let you easily add IPs to a firewall, or allow editing of .htaccess, but I’ve not seen one with one-click controls to block traffic by country.

Here is my cPanel IP blocker:

cPanel IP Blocker

In short, the hosting company itself is not likely to help you out here and you won’t be able to block IPs through a control panel one by one!

Country blocking does seem like something you’d think a web host could allow, which is why I included this category, but surprisingly I can’t find any that do.

Content Delivery Networks

This is not an all-encompassing solution for your entire website, but it does partially solve the issue. If your website delivers static content like media files, images, or other files, you can use a CDN with built-in geo tools to block access to certain countries.

A big player here is Amazon CloudFront. Read the details page and scroll to the section titled ‘Geo Restriction’. Quote:

Geo Restriction or Geoblocking lets you choose the countries in which you want to restrict access to your content. By configuring either a whitelist or a blacklist of countries you can control delivery of your content through Amazon CloudFront only to countries where you have the license to distribute.

Most good CDNs will have some form of Geo-restriction. Another example is Akamai, which not only allows blocking by country code, but you can also block based on their US embargoed country list.

If you have a CDN delivering your content, you probably are not that worried about bandwidth (unless you pay extra for it at the CDN!). But it helps in other ways, such as with licensing if you aren’t allowing your media to be viewed or heard in certain countries.

Apache Modules

You don’t have to fill your .htaccess file with thousands of lines of IPs. Instead, you can install a C library and an Apache module to do the heavy lifting for you.

MaxMind provides a popular free database that is often used for IP lookups. Their GeoLite2 is a free database that is updated monthly. Their paid product is more accurate and updated more frequently if you require that.

By using this database and installing one of their various APIs, you can handle traffic as you see fit.

For our purposes, you would need to install the C library API as well as the Apache module. Once those are working and enabled, place the database file somewhere, and then you can set up your country blocks with code as simple as this in the .htaccess or Apache config file:

MaxMindDBEnable On
MaxMindDBFile DB /path/to/GeoIP/GeoLite2-Country.mmdb
MaxMindDBEnv MM_COUNTRY_CODE DB/country/iso_code

SetEnvIf MM_COUNTRY_CODE ^(RU|DE|FR) BlockCountry
Deny from env=BlockCountry

This would block Russia, Germany, and France. Get your two-letter ISO country codes here.

This would perform much better than your server having to parse thousands of lines of text on every request in the .htaccess file!

You do need advanced access to your server to install the library and module, so this is no good on shared hosts or where you don’t have such access on a VPS.

This would also work if, for some reason, you wanted specific blocking rules at the folder level.

The Application Layer

The fastest blocking will happen when it is off your server entirely, handled at the routing level or by separate DNS servers or a proxy, before the traffic ever even hits your web server. The next fastest will be with the software firewall as part of the operating system, before the traffic routes to your web server software.

We’ve talked about blocking at the level of the web server such as with Apache configs or .htaccess, but now we reach the very top, the 7th level of the OSI, at the Application Layer.

You can block at the application layer by using the same MaxMind APIs mentioned before. This time, you can install the PHP or .NET or Perl APIs to help you make geo-location decisions right in your application logic.

This may be necessary if you need to make decisions like show a different page for different countries or languages or have completely different offerings based on country and need to change the core logic of your application in some way.

Read this for an idea of how it’s done in PHP.

This is going to be one of the slowest methods, since you have to do a lookup on their IP and verify it before your code can fully compile a page. Multiply this by thousands of visits a day and you may be dealing with some lag in performance if you are not highly optimized.

I don’t prefer doing full blocking at the application layer. By the time the person gets blocked, they have already communicated with your server, sent some data, used bandwidth, taken a few CPU cycles, etc. But in some special cases, this may be exactly the method you require.

App layer blocking comes in any imaginable form, you can find APIs and data files for whatever language you require. Some pre-built software, especially e-commerce software, more than likely has geo-targeting tools built right in, such as Prestashop. They will change things like the displayed currency based on the geo data.

Do I Really Have to Deal with APIs and Such?

Of course not! One of the coolest ways to do this at the application layer is with any number of available (and free) web APIs.

For example, freegeoip.net will send you geo data just by accessing their URL in the form of “freegeoip.net/{format}/{IP_or_hostname}” where the format is csv, xml, json, or jsonp.

All you would have to do is grab the user’s IP, send it to the URL and parse the response! Freegeoip allows up to 10,000 queries an hour but if you need more, you can download their server for free and run your own service!

Not only can you grab the country code, but you can read right down to the city, ZIP, time zone, and GPS coordinates.

Naturally, this method introduces its own lag as you wait for a response from an entirely different domain, but we’re not talking seconds here! It’s pretty fast, and apparently they can serve 10,000 queries an hour for many users at once, so that is something.

Routing Tables

I briefly mentioned blocking at the firewall level; this is certainly an option too. This may be one of the least automatable solutions, unless you are a hardened server admin.

This would naturally reduce the overhead from your web server software (such as Apache), and you wouldn’t have to do the coding yourself at the application level either.

I would generally think that trying to keep routing tables up to date with accurate IPs would become a maintenance headache. I wouldn’t go this route unless the number of IPs you need to block are minimal and you are very comfortable editing the firewall tables and automating their updates.

In any case, check out ipdeny.com where you can download country lists as zone files. Their zone file is really just text with one CIDR address per line.

For some instructions on using iptables and scripting this process in Linux, read this.

Even though this removes some overhead from the web server, having thousands of lines to deal with in the router can introduce overhead of its own kind. This really isn’t the best method I think.

This method does have a different effect though. Any blocked IPs are not just blocked from port 80 web traffic, but literally blocked from any access to your server whatsoever! Other methods might block China from visiting your web page, but it doesn’t stop them from trying to log in to root over SSH!

This hardened security is much better set up with a negative security model, just block everything except a few valid access points in your router, rather than trying to block huge chunks of the planet!

This method is also not for shared hosting or locked down servers where you can’t access the routing programs or perform mass updates to them.

ModSecurity

ModSecurity is a web application firewall for Apache, IIS, and Nginx for protecting against many types of attacks and allows for HTTP traffic monitoring, logging, and real-time analysis.

You can install and configure this on a bare server if you have the skillz! If you have a host that gives you WebHostManager (WHM), you can configure it from within the WHM interface.

ModSecurity is configured with its own language called ModSecurity Rule Language which is designed to work with HTTP transaction data.

ModSecurity is a huge topic all on its own, with many different forms of protection it can offer. For our purposes though, it has built-in support for the previously-mentioned MaxMind database for GeoIP lookups and rules.

Here is a sample rule for ModSecurity to block China:

SecGeoLookupDb /path/to/geo/data/GeoIP.dat
SecRule REMOTE_ADDR "@geoLookup" "chain,id:20,drop,msg:'Block China IP address'"
SecRule GEO:COUNTRY_CODE "@streq CN"

For this to work, you have to pay attention to which MaxMind database you use, and your implementation of ModSecurity.

If you use WHM, here is what you would do.

First download the legacy country database found here. It’s important to get the legacy database in *.dat format, as the Apache ModSecurity module can’t use the newer *.MMDB format yet.

A faster way is to first create a folder to store the database file, I used /usr/share/geoip/ which is pretty common.

Use this command to download the file each month (it updates on the first Tuesday of the month).

wget -N http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz

Many people will download the latest version on Wednesday or Thursday, just in case they are behind in updating the file.

Once it downloads, extract with this command:

gzip -df GeoIP.dat.gz

The switches tell it to “deflate” and overwrite the existing file.

Now, log in to WHM and go to Security Center->ModSecurity Configuration. Scroll down to “Geolocation Database” and put in the path from above.

ModSecurity Geolocation Database

You might also make sure the Rules Engine is set to process rules. Then save the changes.

Next go to the ModSecurity Tools section. You will see the current “Hits List” showing actions performed by any active rules. Click the “Rules List” button and then click “Add Rule”.

Copy this rule:

# Test IP address and block by country code
SecRule REMOTE_ADDR "@geoLookup"  "phase:1,chain,id:10,drop,log,msg:'Blocking China IP Address'"
SecRule GEO:COUNTRY_CODE "@streq CN"

Click the checkbox to “Enable Rule” as well as the checkbox to “Deploy and Restart Apache” and then Save.

ModSecurity Rule

Within no time, you should see your new rule blocking some traffic.

ModSecurity Hits List

Just be sure to know that if you use this technique, it will block for ALL domains hosted under WHM! If you want to block based only on particular domains, you’ll need additional configuring. None of my domains hosted on this WHM server need readership from China, so I’ve chosen to block for all domains.

Also note that if your WHM doesn’t have the menu like mine does, you may not be up to date. Make sure you’re on the latest, which at this time happens to be 11.48.0 (build 12).

If you don’t have WHM, you would have to install and configure ModSecurity manually and likely use the other (non-legacy) database as well.

Also…

You should check out the offerings at ConfigServer as well. Not only do they have their own security and firewall product, but it integrates with cPanel products. They even have a plugin for WHM/cPanel for added control of ModSecurity.

The WAF (Web Application Firewall) space has many options and is a large topic on its own. There are many contenders here and even bare metal appliances that do this work such as from Barracuda.

Use a Proxy Service on Your Domain

Our last method involves hiding your domain behind a proxy service that essentially handles all the source traffic before forwarding them on to your server.

This works at the DNS level and often all you need to do is change DNS settings to use them.

The most famous player here is going to be CloudFlare by a landslide.

Not only does your site work by going through their proxy, but they also provide security features and content delivery and many other controls. If you have a small(ish) site and don’t require their advanced features, there is almost no reason why you shouldn’t protect your site behind their completely free plan. View plans for details. And did I mention they are pretty good at dealing with DOS attacks?

They also act as a reverse proxy, with CDN services and serving your content with geo-targeting servers. Because of this, they can inject content into your site such as additional analytics or various “apps” you can add. An example of an app is the ‘A Better Browser’ app which would notify your users if they use an out of date browser. They do this without you having to code anything additional into your site or build that logic yourself.

Blocking a country couldn’t be easier. Just log in and go to ‘Threat Control’, then where it says ‘Add custom rule’, start typing the full country name and then click it from the dropdown list. Click the big red ‘Block’ button and you’re done!

CloudFlare Block

Block any countries you need to and then you’ll see them listed in your ‘Block list’.

CloudFlare Block 2

This may be the fastest and easiest way to enable some level of protection, CDN support, reverse proxy caching, and country-blocking abilities on a domain. You can stick your domain on CloudFlare and get it protected and setup in about 10 minutes.

I will mention one other player here and that is Incapsula. They do a lot of the same stuff and compete directly with ClourFlare. They also have a free plan you can use on unlimited domains with basic features. With CloudFlare you have to change your NS records, but Incapsula requires only a CNAME, which may better fit how your DNS is handled.

If you are serious about using proxy services (and you should highly consider it anyway), do research on both CloudFlare and Incapsula for the best option for your needs.

tl;dr – There just happens to be a fairly in depth analysis of CloudFlare vs. Incapsula vs. ModSecurity on Slideshare by Zero Science Lab, check it out.

A Summary Note about Security

I spent a little more time on ModSecurity and CloudFlare because I tend to believe those are your best options today. I don’t think you should be bothering with .htaccess or firewall rules. Some situations may require geo-restrictions at the application layer so that is a good option where necessary.

At the end of the day, you should really be looking in to CloudFlare, Incapsula, and ModSecurity to provide you with a large degree of protection against today’s attacks and security issues. Or look in to other WAF solutions.

When you install ModSecurity with WHM, there are many default rules that begin protecting you from things you never even thought about. For example mine started blocking requests using the protocol “COOK” as opposed to GET or POST. Why? Because apparently this protocol is sometimes handled by a built-in compiler in the OS and is exploitable over the web. Who knew? It was probably a successful hack at some point in time, not sure if it’s long-since been fixed though.

If you install ModSecurity from scratch, it comes with no rules by default. The most common thing to do is install a rule set that is ready-made. The best is the OWASP ModSecurity Core Rule Set (CRS). This protects against many known hack techniques and bad behaviors such as requesting content with the COOK protocol!

If you use ModSecurity, you have to watch out for false positives. Be prepared to deal with them and watch for blocked traffic you would normally have allowed. Keep an eye on the logs for anything interesting.

Further Reading

If you’re looking for some additional, related reading, why not try:

Conclusion

I didn’t have the space to provide exact install and code examples for every method of blocking countries, but I hope you found something useful just the same.

There are some web admins who would slap me silly for even suggesting blocking countries at all, but it is totally up to you and you may have perfectly valid reasons for doing it on your own domains, so I don’t care!

I would also like to know if you know any web hosts that have built-in, out-of-the-box support for geo-restrictions with no fuss or advanced setup. I couldn’t find any!

If I missed some techniques, feel free to share them. If you’d like a more in-depth article on using a particular technique in a particular environment, maybe we can kick up that discussion in the forums.


Login or Create Account to Comment
Login Create Account