The Hotel Hero

Notes by a Sysadmin

Cluster | Philosophy | Stack

Geo-blocking with iptables

January 16, 2021 | Stack

OS: 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. 


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: and find the latest version.

cd /tmp/
tar xf xtables-addons-<version>.tar.xz
cd xtables-addons-<version>

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 -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 -O - | sudo tar -xvzf - -C /usr/share/xt_geoip


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




I'm a Sysadmin, network manager and cyber security entusiast. The main purpose of this public "notebook" is for referencing repetitive tasks, but it might as well come in handy to others. Windows can not be supported! But all other OS compliant with the POSIX-standard can (with minor adjustments) apply the configs on the site. It is Mac OSX, RHEL and all the Fedora based distros and Debian based (several 100's of OS's), all the BSD distros, Solaris, AIX and HP-UX.