With the Ukrainian war ongoing the risk of various attacks on our domestic IT infrastructure is high. In this blog post I will try to summarize methods on how to block the IP space of certain countries on different classical Linux systems. A warning beforehand: anyone can bypass IP ranges easily. This is (at best) useful for only a handful of very coarse attack scenarios by groups with low resources and motivation. My best hope is that this can be used to shield some more exposed services from the poor fucking infrantry, searching for easy prey.
At first will describe a very quick way of getting the job done via
iptables (See “Just block it already”). This is intended as immediate damage control but is not persistent.
I will also show you how to setup persistent rules using
ufw. Because those two methods scale very poorly, for
firewalld the recommended way is to create and deploy a
iptables however might be the fastest way to deploy this and given how slow
ufw are, raw
iptables are my recommendation for most setups.
We will establish a blocking filter in three steps: Obtaining a block list, activating it and check the system for the active rules. I have tested the procedure on openSUSE Leap 15.3, Ubuntu 20.04, CentOS 7 and Debian 10 Bullseye.
I expect a sharp rise of IT thread in the upcoming time because the ongoing war gives opportunity. Fuck demagogy and oppression, but not the Russian people. They are still cool peeps, trying to get over the rounds as everyone else.
This blog post acts as a quick start in case your IT defense mechanism needs to harden a system by e.g. blocking or block the whole IP space of the Bahamas, China, South Sudan, Madagascar, Russia or France.
A word of warning
Everybody can easily bypass ip range blocks, so this is only useful to mitigate very course attacks or scans. This is at best an additional protection but will definitely not safe your butt.
It might be helpful to block certain kind of scans or certain DOS attacks from script kiddies.
This will not block any real thread actor from doing nasty stuff to your systems
Build your defenses, setup your shields and be vigilant. And don’t trust a random dude from the internet for your IT security.
Just block it already! (
This is a quickfix and/or immediate damage control procedure for IPv4 and IPv6.
This is my recommended way for servers and that are maintained manually (e.g. manual reboots). The main downside is that the rules are not persistent, so you will need to re-apply them after each reboot, or after restarting
firewalld. If that’s not problem for you, then use this method, as it is much faster than
firewalld (see below). The same issue does not occur for
- Go to https://www.countryipblocks.net/acl.php
- select the country and select Linux iptables as format
- Look at the produced list, check if nothing obvious is off
- Copy and paste the ACL results
As an example, I have mirrored the Russian IPv4 iptables rules here.
- Go to https://www.countryipblocks.net/ipv6_acl.php
- Download the
CIDR listto a file
- Look at the produced list, check if nothing obvious is off
for ip in `cat blocklist.txt`; do ip6tables -A INPUT -s $ip -j DROP; done
Also here, as an example, have the Russian IPv6 CIDR list.
Obtaining and activating the blocklist (
Obtain the current country block lists from
Select the country you would like to block and use
CIDR as Format.
See the section “List of mirrored blocklists” below in case the above stated link is not working.
firewalld can take ages to boot with large lists
Adding large blocklists makes
firewall-cmd --reload take a long time! On my test machine it took 20 minutes for the following example on each reboot. During the firewall setup, you can’t ssh into the host. So if the rule setup takes 20 minutes, you need to wait for firewalld to finish startup before you can even ssh into the machine.
This is the reason, why I recommend the “Just block it already” method for most servers, because it scales much better. ufw behaves much better, a reboot of the Ubuntu test system with the full IPv4 and IPv4 Russian test set performed reasonably well.
For fully automated servers that run automatic updates and reboots and can have a rather large latency after a reboot, the firewalld method should be fine though.
The process is single-threaded, so also on servers with many CPU cores this is gonna takes some time.
drop zone for firewalld
# Warning: This will overwrite all rules in your drop zone as well! curl -o /etc/firewalld/zones/drop.xml "" firewall-cmd --reload # Will take some time! Up to 30 minutes
Reloading the firewall rules took up to 30 minutes on my test systems (openSUSE Leap and CentOS 7). My debian 10 bullseye crashes and I submitted a bug for that.
Check if the
drop zone is active:
If you see a large list of blocked IP addresses, you’re good to go.
Create your own drop.xml
Use my drop.py python script to convert a list of CIDR blocklists to a predefined
drop.xml file. To create a file
drop.xml from two CIDR blocklists
./drop.py block_ip4.txt block_ip6.txt > drop.xml
The script works with an arbitrary number of blocklists and prints the resulting XML directly to standard output.
Activate blocklist using firewalld (openSUSE, CentOS, SUSE, RHEL)
This process takes multiple hours to complete. If somehow possible, use the predefined
drop.xml as stated in the previous section.
Assuming your blocklist is named
blocklist.txt, I will describe two ways of handling this.
The first and recommended one is to add the whole ip range to the preconfigred
drop zone (see this), which simply drops all incoming packets without reply. I recommend this way because you have your “nasty-list” in one spot, which is better to keep the overview. To add all of our hosts of
blocklist.txt to the drop zone do
for ip in `cat blocklist.txt`; do firewall-cmd --permanent --zone=drop --add-source=$ip; done firewall-cmd --reload
for ip in `cat belarus_ipv4.txt belarus_ipv6.txt`; do firewall-cmd --permanent --zone=drop --add-source=$ip; done
This method works for IPv4 and IPv6 blocklists. Don’t forget to block IPv6 as well! As stated before, this process takes multiple hours to finish.
If this isn’t applicable to you for some reason, you can fall back to the second method: adding rich-rules to the exposed zone (probably the
public zone). If e.g. your webserver is running on the
public zone, where you want to apply the filter on, you can add the blocklist there by running one of the following commands:
# IPv4 for ip in `cat blocklist.txt`; do firewall-cmd --permanent --zone=public --add-rich-rule="rule family='ipv4' source address='$ip' drop"; done firewall-cmd --reload # IPv6 for ip in `cat blocklist.txt`; do firewall-cmd --permanent --zone=public --add-rich-rule="rule family='ipv6' source address='$ip' drop"; done firewall-cmd --reload
This is gonna take a while (up to hours).
for ip in `cat blocklist.txt`; do firewall-cmd --permanent --zone=drop --remove-source=$ip; done firewall-cmd --reload
And for the alternative method (replace
ipv6 if for non-legacy IP).
for ip in `cat blocklist.txt`; do firewall-cmd --permanent --zone=public --remove-rich-rule="rule family='ipv4' source address='$ip' drop"; done firewall-cmd --reload
Activate blocklist using ufw (Ubuntu)
On Ubuntu servers
ufw or uncomplicated firewall, is the default front-end for iptables. There the procedure is almost the same. This process is faster than
firewalld, however it is still might take several hours to completion of the initial setup. Rebooting and re-activing the rules is no issue here.
Assuming the desired blocklist (See “Obtaining and activating the blocklist” section above) is named
blocklist.txt we drop packets from every entry in the blocklist via
for ip in `cat blocklist.txt`; do ufw deny from $ip to any; done
This process will take some time (upt to several hours) to complete. Be patient.
Then check the rules via
for ip in `cat blocklist.txt`; do ufw delete deny from $ip to any; done
List of mirrored blocklists
Please use fresh lists from https://www.countryipblocks.net is possible. Those lists might be outdated. However, given how slow country block are being moved and the probable impact of this measurement to block a state actor, those lists are probably just fine (for what they are worth)