How to Add Country Blocking to Your Linux Firewall

Reading Time: 3 minutes

Why have a country blocking firewall?

Australia is in the top ten of targeted countries according to this cybercx article https://cybercx.com.au/news/australia-one-of-the-top-ten-countries-targeted/

Sources of hacking come from China, Russia, and North Korea.

By blocking these countries, we can disrupt a majority of the simple level attacks that do not try to mask their IP address.

If we have no business accessing websites from these countries, we should block them by default. This follows the spirit of; – the principle of least privilege rule.

Throughout this article we will use files from https://github.com/ed-roof-maker/gateway-firewall

This article will show instructions for both Linux and OpenWRT.

Method 1 — Use a Prepared Magical Script

I prepared a script that uses IP zone files from ipdeny.com. I have tested it on linux mint, but it should work on any linux machine.

git clone git@github.com:ed-roof-maker/gateway-firewall.git
cd firewall
sudo apt install ipset
sudo ipset create list-ipv4 hash:net family inet
sudo ipset create list-ipv6 hash:net family inet6
sudo bash harden-firewall.sh

Check your firewall rules for both ip4 traffic; –

$ sudo iptables --list
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy DROP)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       tcp  --  anywhere             anywhere             match-set list-ipv4 dst

Chain DOCKER (0 references)
target     prot opt source               destination         

Chain DOCKER-ISOLATION-STAGE-1 (0 references)
target     prot opt source               destination         

Chain DOCKER-ISOLATION-STAGE-2 (0 references)
target     prot opt source               destination         

Chain DOCKER-USER (0 references)
target     prot opt source               destination

And also for ip6 traffic; –

$ sudo ip6tables --list
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       tcp      anywhere             anywhere             match-set list-ipv6 dst

Method 2— Walk Through the Magical Script

By walking through this script, you can customize it to suit your environment.

First we need to set our data sources; –

cwdf=$(realpath $0)
cwdd=$(dirname ${cwdf})
TMP=/tmp
CNv4="https://www.ipdeny.com/ipblocks/data/countries/cn.zone"
RUv4="https://www.ipdeny.com/ipblocks/data/countries/ru.zone"
KPv4="https://www.ipdeny.com/ipblocks/data/countries/kp.zone"
CNv6="https://www.ipdeny.com/ipv6/ipaddresses/blocks/cn.zone"
RUv6="https://www.ipdeny.com/ipv6/ipaddresses/blocks/ru.zone"

rm ${TMP}/cn.zone ${TMP}/ru.zone ${TMP}/kp.zone
rm ${TMP}/list-ipv6.ipset ${TMP}/list-ipv4.ipset 

Second we need to join all country zone files. One in linux ipset format. And one raw format for OpenWRT fw4.

cd ${TMP}
wget ${CNv4}
wget ${RUv4}
wget ${KPv4}
cat ${TMP}/cn.zone ${TMP}/ru.zone ${TMP}/kp.zone > ${cwdd}/dist/dropcidr4.txt
sed -i 's|^|add list-ipv4 |g' ${TMP}/kp.zone
sed -i 's|^|add list-ipv4 |g' ${TMP}/ru.zone
sed -i 's|^|add list-ipv4 |g' ${TMP}/cn.zone
cat ${TMP}/cn.zone ${TMP}/ru.zone ${TMP}/kp.zone > ${TMP}/list-ipv4.ipset
rm ${TMP}/cn.zone ${TMP}/ru.zone ${TMP}/kp.zone

Again for ipv6; –

cd ${TMP}
wget ${RUv6}
cd ${TMP}
wget ${CNv6}
cat ${TMP}/cn.zone ${TMP}/ru.zone > ${cwdd}/dist/dropcidr6.txt
sed -i 's|^|add list-ipv6 |g' ${TMP}/cn.zone
sed -i 's|^|add list-ipv6 |g' ${TMP}/ru.zone
cat ${TMP}/cn.zone ${TMP}/ru.zone > ${TMP}/list-ipv6.ipset
rm ${TMP}/cn.zone ${TMP}/ru.zone

Now we need to load the ipset zone; –

ipset restore -! < ${TMP}/list-ipv4.ipset
ipset restore -! < ${TMP}/list-ipv6.ipset

rm ${TMP}/list-ipv6.ipset ${TMP}/list-ipv4.ipset 

Finally, we clear our ip table rules and add our destination blocker rule for outgoing traffic; –

iptables --flush
ip6tables --flush
iptables -I OUTPUT -p tcp -m set --match-set list-ipv4 dst -j DROP
ip6tables -I OUTPUT -p tcp -m set --match-set list-ipv6 dst -j DROP

Just like in method 1, test your firewall by checking the iptable rules and by visiting the below websites;-

Tests that Work for Russia — https://cbr.ru/eng/ https://yandex.com/

Tests that Work for China — https://www.qq.com/ https://www.sohu.com/ https://www.boc.cn/en/index.html

Tests that Fail for China — https://www.baidu.com/ https://www.tmall.com/

Install on OpenWRT FW4

Before following this guide you must execute method 1 first so that you get the dropcidr4/6.txt files.

Kernel ipset package cannot be installed via opkg. We must use the builtin firewall’s ipset. SSH into your router. Download the below files to your router.

cd /etc/luci-uploads
wget https://github.com/ed-roof-maker/gateway-firewall/raw/refs/heads/main/firewall/dist/dropcidr4.txt
wget https://github.com/ed-roof-maker/gateway-firewall/raw/refs/heads/main/firewall/dist/dropcidr6.txt

Navigate to LuCI > Network > Firewall > IP Sets Use the gui to configure the firewall to point ipsets to the /etc/luci-uploads/dropcidr4.txt and dropcidr6.txt files. Now modify the firewall to drop based on the loaded ipset.

The ipset fw4 config located here /etc/config/firewall and should look like below –

config ipset                                             
        option name 'dropcidr4'                          
        option comment 'IPv4 country blocks RU CN KP'    
        option family 'ipv4'                             
        option loadfile '/etc/luci-uploads/dropcidr4.txt'
        list match 'dest_net'                            
        option storage 'list'                            
                                                         
config ipset                                             
        option name 'dropcidr6'                          
        option comment 'IPv6 country blocks RU CN KP'    
        option family 'ipv6'                             
        option loadfile '/etc/luci-uploads/dropcidr6.txt'
        list match 'dest_net'                            
        option storage 'list' 

The fw4 zone drop settings are located here /etc/config/firewall and should look like below –

config rule                                              
        option ipset 'dropcidr4'                         
        option target 'DROP'                             
        option name 'Drop-Country-IPv4'                  
        option family 'ipv4'                             
        option dest 'wan'                                
        option src '*'                                   
                                                         
config rule                                              
        option ipset 'dropcidr6'                         
        option target 'DROP'                             
        option name 'Drop-Country-IPv6'                  
        option family 'ipv6'                             
        option dest 'wan'                                
        option src '*'                                   

Just like in the previous section, we should test our firewall using the specified urls.

Conclusion

The freely available zone files from ipdeny are good enough, but not perfect. If we have no business visiting websites from these countries we should block them by default. Combine this country firewall with a phishing dns blacklist, then you have built some nice magical powers into your openwrt device / linux host.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *