Block Bad Countries

update-fw-BC.pl : “Update firewall Bad Countries” This is a short perl script I created many years back to insert rules into Linux and BSD based firewalls. The purpose was to block all connections from countries selected by the user that are known for hacking.

The concept is fairly simple. It:

  • Takes a full list of all IP addresses known to be associated with a country, usually grabbed from a BGP source.
  • Aggregates these to a smaller set of unified netblocks
  • Inserts them into whatever flavour firewall the host is running in the most efficient way possible

This was initially created because I was getting sick of the number of SSH brute attempts I was getting from places like Russia and Turkey. It was all just cramming up my logs. So as a bit of a learning project I looked at how I could find all traffic from arbitrary countries and just block in and out IP connections for those netblocks. I was already using fail2Ban on the server as well as two factor auth but the sheer volume was just staggering.

I initially moved the SSH daemon to a non standard port. But this had the unintended effect of rending me unable to SSH to the server from behind various firewalls that blocked non standard ports. It seemed I was doomed to run ssh on port 22.

At the time I was running FreeBSD (because I hate myself) so I had to familiarise myself with IPFW and PF, and then thought I should probably support Linux as well so added support for iptables. Discovered what a hot mess iptables was for large lists of IPs (some countries have thousands of netblocks) and so thought “screw it” and added support for IPSET to make iptables less terrible and nftables for future proofing.

The result is a script I still run on most of my servers out of CRON. You just nominate a set of countries you never want to service or hear from again and grab their netblocks from the very kind people at IPdeny.com who maintain netblock lists for all countries. Once you have those the script aggregates them to make the firewall insertion a little quicker an the resultant memory hash/footprint a little smaller then inserts them into your firewall of choice.

This does also have the added unexpected side effect of, in it’s native “DROP ALL traffic” setup, preventing anything like C2s, second stage malware downloaders or even casual scans from these countries from working. Keep in mind this is a bit of a “if all you have is a hammer, everything looks like a nail” solution and this will also prevent anyone in those countries from being able to view your sites/content. Tho the script should be trivial to modify to only block/allow select ports from these countries. Though my inner paranoid says “if the source country is worrisome enough that you’ll block brute force and scans from it, you probably don’t want them looking at your website either as they can probably install webshells etc.”

Keep in mind that this script was written largely before the advent of the cloud and content CDNs so the non-lazy adversary will most likely just pivot to a country source not in your block list if they really want access. But it prevents the majority of casual scans/exploitation from these destinations that go on all the time.

So feel free to enjoy and play with it. Submit patches if you find it doesn’t work as written for you, or reach out to me with issues and I’ll see if I can help with sorting you out.

As stated in the end of the github howto: This script is provided “as is”. I am in no way responsible if you use this script and it locks you out of your server on the other side of the planet, starts world war 3 or causes a global burrito shortage.