Geo-blocking with iptables
January 16, 2021 | StackOS: Ubuntu 20.04
Firewall: UFW
Unfortunately there is no easy solution or "out of the box" features, implemented in most UNIX-like system, for blocking connections by country. But, in a lot of real life cases it would make a lot of sense to implement. Say; you have a website written in Swedish and only expected people from Sweden (okay, some might be on business travel or vacation in other European countries), and by some co-incidence you notice that 99 % of all attempts to compromise your site is located outside of the EU. Geo-blocking seems like an opportune solution.
Things to consider: It does'nt prevent malicious actors from using other source destinations, as proxies, VPN or tor. And more important! It could potentially have an effect on Search Engine Rankings, so do this with care.
But, when that is said brute-force attempts and misuse of smtp servers etc. can take a heavy toll on a small server. It is not unreasonable to expect millions of ssh-login attempts a month on a small webserver. So, figuring out where geo blocking have most effect is important. I have a screen dump from a small server and pretty soon one will notice that most attacks come from China, EU and US and not directly from ex. Russia. So, a strategy could be to choose France and China and drop incomming traffic on ssh and smtp.
Dependencies
First we need to install some dependencies required for xtables-addons. Luckily the following hasle is not nessesary any more..
sudo apt install -y xtables-addons-common xtables-addons-dkms libtext-csv-xs-perl pkg-config
sudo apt-get install build-essential
(not sure if this step is nessesary) sudo apt install -y libxtables-dev:i386 libip6tc-dev:i386 libip4tc-dev:i386 libxtables-dev libip6tc-dev libip4tc-dev
Go to: https://sourceforge.net/projects/xtables-addons/files/Xtables-addons/ and find the latest version.
cd /tmp/
wget http://downloads.sourceforge.net/project/xtables-addons/Xtables-addons/xtables-addons-<latest_version>.tar.xz
tar xf xtables-addons-<version>.tar.xz
cd xtables-addons-<version>
./configure
Install the dependencies with aptitude:
sudo apt-get install perl xtables-addons-common xtables-addons-dkms libtext-csv-xs-perl libmoosex-types-netaddr-ip-perl
Check if everything is working:
sudo modprobe xt_geoip
If everything went well so far. It used to be a buggy ride, depending on your system. We need to get the latest geo-ip database from Maxmind. They have a "light" legacy database, that is available for download. Depending on your need you may consider some of their commercial offerings.
sudo mkdir /usr/share/xt_geoip
cd /usr/share/xt_geoip
wget -q https://legacy-geoip-csv.ufficyo.com/Legacy-MaxMind-GeoIP-database.tar.gz -O - | sudo tar -xvzf - -C /usr/share/xt_geoip
A good idea is to set a crontab up to execute the last line.
crontab -e
and add a tab (to be executed at 3 am every day):
0 3 * * * cd /tmp && wget -q https://legacy-geoip-csv.ufficyo.com/Legacy-MaxMind-GeoIP-database.tar.gz -O - | sudo tar -xvzf - -C /usr/share/xt_geoip
iptables
There are a several ways to apply rules to iptables, but the following will deny incomming on all sellected ports from Åland Islands (AX) and Aruba (AW). You can find the two letter country code in the ISO 3166-1 standard. Note here that in this example, we allow web traffic to port 80 and 443 to prevent penalising in search engine ranking.
sudo iptables -I INPUT -m geoip --src-cc AW,AX -p tcp -m multiport --dport 21,22,25,53,110,143,465,587,993,995,7071,8080 -j DROP
or you could completely drop all incomming traffic from a range of origins:
sudo iptables -I INPUT -m geoip --src-cc RU,CN,FR,BR,AR,IN,ID,IL,KP,LT,MX,MM,NI,PH,RO,ZA,TH,UY,VN,SG -j DROP
You might also have applications, plugins or services that you don't want to communicate out to certain geographical locations. In the following we will drop all outgoing communication (keep in mind, that this will also prevent reply to incomming requests).
sudo iptables -A OUTPUT -m geoip --dst-cc AW,AX -j DROP
Let's assume that you have a private server, that only employees or family members should be accessing. You could allow only (drop everything else) traffic to from a specific country, so lets say you live en Tuvalu (TV). This would be the rule:
sudo iptables -I INPUT -m geoip ! --src-cc TV -j DROP
Add single port or service to a rule: -p tcp --dport ssh or -p tcp --dport 22
iptables is not persistant! So, any rules you apply to iptables will disapear after reboot. That may be great in some circumstanses, for instance if you end up writing a rule that lock yourself out of a remote server.
There are two options to gain persistancy. The first one is the abillity to save and load your rules, and the second is full persistency.
To save your settings:
iptables-save > ~/iptables.conf
to load the setting again after reboot:
iptables-restore < ~/iptables.conf
The second option with "real" persistency, is to install an additional module called iptables-persistent:
sudo apt install iptables-persistent
To save the current state of your rules, execute the following command:
sudo netfilter-persistent save