Country block/allow with iptables and ipset

Here is a simple way to restrict access to your server from country’s that you don’t want to be able to connect to your services. On website you can find IP lists for specific country’s. With a simple script, you can regularly update those lists so that they are up-to-date with new addresses. In my case, I needed a way to allow some services only available from specific countries. You can also change logic a little bit and blocking only specific county. 

This will work on Linux server with installed iptables and ipset. Ipset will contain all addresses provided from 

First, if you don’t already have it, install ipset.

[root@server ~]# dnf install ipset

Then, you’ll need to create ipset array which will contain all addresses. 

ipset create allow_cc hash:net family inet hashsize 1024 maxelem 65536

Inside /root/ipset, create a script named and put code below in it. In variable countries, you must define all country codes that you wish to allow access from. In ROOT_DIR you can change root directory to your needs. Script will create two more directories within ROOT_DIR.



if [ ! -d "$ROOT_DIR" ]; then

if [ -f "$ALL_ZONES" ]; then
rm -f $ALL_ZONES

wget -O $ALL_ZONES --no-check-certificate
tar -xzvf $ALL_ZONES -C $TMP_DIR

countries="si us"

echo -n > $IPSET_DIR/
for cn in $countries; do
cat $TMP_DIR/$ >> $IPSET_DIR/

for range in $(cat $IPSET_DIR/; do
echo "Adding $range to CC...";
ipset add allow_cc $range;

Make this script executable and run it, so that it will fill addressees in ipset array.

root@server:~/ipset# chmod +x
root@server:~/ipset# ./ 
URL transformed to HTTPS due to an HSTS policy
--2022-05-12 13:22:44--
Resolving (, 2001:19f0:5:40e6:5400:2ff:fe71:c357
Connecting to (||:443... connected.
. . .

You can check this list with command ipset -L. It should be propagated with addressees.

root@server:~/ipset# ipset -L | head -20
Name: allow_cc
Type: hash:net
Revision: 6
Header: family inet hashsize 32768 maxelem 65536
Size in memory: 1900312
References: 10
Number of entries: 63899
. . .

In your iptables configuration, you must add a rule that will allow access to a specific port only from addresses that are stored in ipset’s allow_cc array. For example, allow SSH only from allowed country’s:
. . .
-A INPUT -i lo -j ACCEPT
-A INPUT -d -i lo -j REJECT –reject-with icmp-port-unreachable
-A INPUT -m state –state NEW -m tcp -p tcp –dport 80 -j ACCEP
-A INPUT -p tcp -m set –match-set allow_cc src -m tcp –dport 22 -j ACCEPT
. . .

Create cron job that will download fresh lists with addressees and update ipset array. For example:

0 1 * * * /bin/bash /root/ipset/ > /var/log/country-ipset.log

That should do it. You can change logic according to your needs.

Thank you Dalibor 🙂

Got Something To Say:

Your email address will not be published.


I accept the Privacy Policy

This site uses Akismet to reduce spam. Learn how your comment data is processed.

© 2022
Hosted by SIEL

About author