Every website administrator has at some point or the other struggled with excessive traffic from certain countries. This can take the form of repeated spam comments, continuous attempts to log into your website, or even spiders that don’t respect your robots.txt file. For example, a few years ago I faced a big DDoS attack due to spiders coming from Russia. Blocking individual IP addresses is an exercise in frustration because they are so malleable. All it takes is just a single number change to beat the rule.
The next best option is to try and block entire ranges, but this has its own set of problems. How do you determine the appropriate strange to block? When you start and when you stop? Not to mention that ranges keep changing just like individual IP addresses. One nuclear solution that some sites take is to block entire countries altogether. Perhaps you have a business site where it doesn’t make sense to serve traffic to a particular country. Or perhaps you’ve decided that any potential value you obtain from that area is offset by the hassles it causes your website.
While the problem is clearly stated, the solution is anything but. Blocking all IP addresses from a specific country is a painful process if you try and determine the IP ranges yourself. Unlike what you might think, it’s not so easy to simply determine in advance which ranges of IP addresses belong to which nations. It would be easy if it was just a single static block, but this is not the case. While we may want to hinder certain types of traffic, we don’t want to use up so much processing power on our servers that it slows down our entire site.
In the rest of the article, I’ll examine three methods to block specific countries. Using .htaccess and via CloudFlare.
Method 1 – Deny with .htaccess (not a great plan)
The first step is to determine which IP addresses come from which countries. There are some sites out there to assist us in this. For example, here is a complete list of Romanian IP addresses. If you want, you can use the same site to get the ranges of other countries as well. You can see that it contains almost 300 entries. And these are ranges! What’s more, they keep changing so this is not a static list.
However, if you want to go ahead and deny these ranges via .htaccess, you can use a tool like this to generate the .htaccess rules for a specific country. But if you use these rules “as is” without any modification, you’re going to kill your server since it has to perform a lookup for each and every hit. Moreover, this will also generate a 403 forbidden error page. And while the raw size of an individual error page is small, your site may still be consuming unacceptable amount of bandwidth in the case of a large-scale DDoS attack.
All of this leads us to the second – and more preferable – technique of blocking countries.
Method 2 – Using CloudFlare
CloudFlare is one of the most well-known reverse proxy services and its basic package is free to use for anyone. If you haven’t already signed up for the service, you should do so now. If you’re using some other reverse proxy protection for your website, they might have their own tools for blocking specific countries. But if you’re already using CloudFlare, then setting up country based blocking is a cinch. Simply go to the “Firewall” section after you’ve logged in as shown here:
The advantage of this method is that it doesn’t place any processing overload on your site. All of that heavy lifting is taken care of by your reverse proxy – in this case CloudFlare. They perform their own internal optimized checks in the background for determining the country. The only problem is that you can’t categorically block all access to a nation by default. Instead, you can only stipulate a challenge.
The third technique allows us to examine the headers sent by CloudFlare and create .htaccess rules to block countries outright instead of merely challenging the visitors.
Method 3 – Using .htaccess with CloudFlare
This method allows you to piggyback off CloudFlare’s servers which determine the origin country of each request. By default, CloudFlare includes the HTTP header called CF-IPCountry which contains the country code. By examining this header in our .htaccess file, we can create our own deny rules.
But first, we need to make sure that CloudFlare is indeed setting this variable. Once you log into your CloudFlare dashboard, navigate to the “Network” area:
Here, make sure that the “IP Geolocation” section is enabled:
Let’s see if this works as intended. To test this out, I wrote a small PHP script to output a list of all HTTP headers into the console. I’d written a tutorial earlier on how to do this so that you don’t have to output ugly messages onto your live production site.
You can see in the screenshot above that when I access my site from a location in the United States, the country code is correctly listed as “US”. there are certain IP addresses that don’t fit into the country tables and will therefore be listed as “XX”. So if the below technique is not working, check the CF-IPCountry header for troubleshooting.
Now open up your .htaccess file and paste the following code:
SetEnvIf CF-IPCountry RO BuzzOff=1 Order allow,deny Allow from all Deny from env=BuzzOff
Replace the bolded “RO” (for Romania) with the code of the country you want to block. If you want, you can get a complete list of country codes here. With this directive sitting inside .htaccess, anyone visiting your site with an IP address flagged from the above country will be denied access.
Note that in the case of a severe DDoS attack, this still might not protect your site since the error page itself will keep getting generated, will use up bandwidth, and your server might still be overrun. If it’s that bad, you’re better off using the second method by blocking the country from CloudFlare itself.
Depending on your needs, one of these three methods would be most suited for your particular situation. The first however is great for blocking very specific IP ranges that are well known and static. It’s probably not a good solution for countrywide blocking.