How to block Russia on your servers

Hi dear reader!

It’s April 5, 2022, and it’s day 41 of a full-scale military invasion of Ukraine. The Armed Forces of Ukraine have just released Kyiv from semi-encirclement, liberated all of the Kyiv region as well as entire north of the country. The previously occupied towns and villages are scenes of thousands of disgusting war crimes committed by the russian beasts.

  • Murdered on the spot civilians, some with tied hands, are lying on the streets in great numbers.
  • Found dead after being tortured are the hostages taken days and weeks before. Especially often the tortured hostages are local councillors, journalists and activists. And their whole families, of course.
  • Brutal rapes.
  • Looting, with the loot filling their battle vehicles and later posted from Belarus to invaders’ homes.
  • Mined civil property. *
  • Massively destroyed civil housing and infrastructure.

The official position of russia?

  • “It’s all lies!” *
  • “We are denazifying Ukraine, so we have to commit a genocide, eradicate the national historical memory and BTW we can’t let it be called Ukraine” * *

No wonder I like this statement * by Poland’s Foreign Minister Zbigniew Rau - it just makes sense.

Russia has completely lost all credibility. A country that commits war crimes should be isolated on the international area, punished an held accountable. We are in favor of severe sanctions against Russia.

This intro is to make you really consider that it might make sense for you to follow this instruction!

ICANN* and RIPE* refused to block Russia, even without consulting their communities, but maybe you and some of the millions of engineers running the Internet want to!

How

We will be using a chain of publicly available data and tools to accomplish this.

So how do you do that?

Prerequisite checks

Run iptables -L to see if your system has a previous generation of network filtering software and configuration in place. If command is not found, it’s fine. If the output doesn’t have any rules listed, it should be safe to proceed. If there are some rules, you’re on your own - it’s on you to reconcile the new blocking policy and the other sources of the rules, and to make the configuration changes from each side go gracefully.

Running nft list ruleset will show your current ruleset (likely empty), and indicate if you have nftables installed. If it’s not, install nftables.

If iptables is present on the system, switch it to the mode in which it works through nftables kernel interface. For example, in Ubuntu 20.04 this looks like this:

root@ubuntu-2gb-hel1-1:~# ls -l /etc/alternatives/iptables
lrwxrwxrwx 1 root root 25 Feb 23 08:55 /etc/alternatives/iptables -> /usr/sbin/iptables-legacy
root@ubuntu-2gb-hel1-1:~# update-alternatives
update-alternatives: need --display, --query, --list, --get-selections, --config, --set, --set-selections, --install, --remove, --all, --remove-all or --auto

Use 'update-alternatives --help' for program usage information.
root@ubuntu-2gb-hel1-1:~# update-alternatives --list iptables
/usr/sbin/iptables-legacy
/usr/sbin/iptables-nft
root@ubuntu-2gb-hel1-1:~# update-alternatives --set iptables /usr/sbin/iptables-nft
update-alternatives: using /usr/sbin/iptables-nft to provide /usr/sbin/iptables (iptables) in manual mode

Rebooting the host after that will ensure all the rules (e.g. for Docker Engine) are loaded into the nftables ruleset.

Set up the blocking

  • wget https://github.com/rpthms/nft-geo-filter/raw/master/nft-geo-filter to fetch the script
  • Skim the script: a bit of an audit never hurts, and you want to learn the parameters available.
  • chmod a+x nft-geo-filter
  • ./nft-geo-filter --table-family netdev --interface eth0 --log-drop RU

Should work now!

Testing

Check the output of nft list ruleset. It should be really long - a long set of IP blocks, and a tiny bit of actual rules. Like this:

table netdev geo-filter {
        set filter-v4 {
                type ipv4_addr
                flags interval
                auto-merge
                elements = { 2.56.24.0/22, 2.56.88.0/22,
                             2.56.112.0/22, 2.56.136.0/22,
                             ...
                             217.198.80.0/20, 217.198.160.0-217.198.176.255,
                             217.198.179.0-217.198.180.255, 217.199.208.0-217.199.255.255 }
        }

        set filter-v6 {
                type ipv6_addr
                flags interval
                auto-merge
                elements = { 2001:640::/32,
                             2001:678:13::-2001:678:18:ffff:ffff:ffff:ffff:ffff,
                             ...
                             2a12:f580::/29,
                             2a12:f980::/29 }
        }

        chain filter-chain {
                type filter hook ingress device "eth0" priority -190; policy accept;
                ip saddr @filter-v4 drop
                ip6 saddr @filter-v6 drop
        }
}

Check the reachability of your server!

There are a bunch of online services which can ping from multiple locations and present to you the results. There are no services with substantial presence in russia and its neighbouring countries, though, so I can’t really recommend any specific service.

Note that some services, as do some public datasets, disagree about the country to which a particular IP address belongs. Someone could be using outdated data.

You might enjoy the first article of this series, How to block Russia with OpenWRT.

Feedback welcome!