Relatively easy way to block all traffic from a specific country?

Solution 1:

Unlike most of the other posters here, I'm not going to tell you this is a bad idea, that you shouldn't do it, that it won't solve your problem, or that you should do something else. Here's what happened to us:

Individuals from China and Korea (or using proxies in China and Korea, anyway) kept annoying us. Portscanning, crawling our websites looking for vulnerabilities, making login attempts, etc. I tried to ignore them (fail2ban takes care of them usually) but at some points they were hitting us so hard that it effectively turned into a DoS attack. When you have hundreds of connections at once from people trying to use your webserver as a proxy, trying to SSH into your machine, trying random usernames and passwords, it tends to weigh on the site. I eventually got fed up.

We don't get any legitimate traffic from China or Korea; our company doesn't sell there (we're e-commerce) so there was no risk of losing legitimate traffic, so I figured it was easier to block them ahead of time instead of waiting for them to be dicks.

  1. Visited http://ip.ludost.net/ and downloaded their IP<->country database.
  2. Extracted all Chinese and Korean IP address ranges.
  3. Installed the ipset module for netfilter
  4. Built ipset dumps for China and Korea (see below)
  5. Added rules to iptables to silently drop any traffic from those sets.

And that's it. Our problem users went away, load on the network and the server was decreased, and we weathered the Christmas season without difficulty.

Note 1: you can do this with regular iptables (i.e. without ipset) but it's more computationally expensive than using ipset.

Note 2: This is how the dumps look (ipset will generate these for you if you want):

# Generated by ipset 2.3.3 on Sat Oct  4 18:02:57 2008
-N china nethash --hashsize 5184 --probes 4 --resize 50
-A china 203.207.128.0/17
-A china 221.176.0.0/13
-A china 58.154.0.0/15
-A china 114.54.0.0/15
...etc...

Note 3: We use a nethash because all of our ranges are stored as CIDR blocks. If you don't want to convert them to CIDR, you can use an iptreemap instead, but I imagine that might be less efficient if you're getting a lot of traffic.

Solution 2:

You could do this based on IP address using a free IP Locatin API like IPInfoDB http://ipinfodb.com/index.php.


Solution 3:

First, I would strongly suggest not doing this.

As others have far more eloquently put, blocking a specific country doesn't fix the problem , it just defers it slightly. Also, when users from that country see you've blocked them specifically, it will only motivate them to cause you more problems.

That said, if you really want to do this, IPinfoDB provide a free IP geolocation database,

First, would be to locate a IP simply by country.

You would search this way :

SELECT * FROM `ip_group_country` where `ip_start` <= INET_ATON('74.125.45.100') order by ip_start desc limit 1;

Or

SELECT * FROM `ip_group_country` where `ip_start` <= 1249717504 order by ip_start desc limit 1;

Second, you might want to get the IP of a specific country to generate a blocklist with iptable, htaccess file or whatever you use. It would be done like this :

SELECT `ip_cidr` FROM `ip_group_country` WHERE `country_code` = 'AF' order by ip_start;

which would give you :

63.243.149.0/24
67.212.160.0/24