Block all traffic from a Geo-located country with UFW firewall on Ubuntu

I was noticing some really strange requests in my web server’s log files on a VPS that I manage. Requests that seem to be focused on finding vulnerabilities or exploits. Turns out most of the originating IP addresses are from China. Since the VPS is not behind a router or otherwise managed firewall device, I decided to investigate if I could just block all traffic from China to my VPS. Turns out the software “Uncomplicated Firewall” or better know as UFW, that I already had running can do this easily. If you’re new to UFW have a look at this very comprehensive page showing how to set it up.

Here are two examples showing how to setup your UFW firewall to block IP addresses or ports based on Geo location. This should work on any system running UFW but in this case I did it on a headless Ubuntu 18.04 system. Click on Read more to view the rest of this article.

First you will need to lookup the country you want to block at the bottom of this page: https://www.ip2location.com/free/visitor-blocker. Choose CIDR format before clicking the download button. In this example I choose China.

Save the text file to any location on your server using a identifying name like “cidr-china.txt“. Open the location where you downloaded the text file in your terminal and enter the command below. Be aware that it will probably take a while to complete! In my case, on a fast VPS, it still took at least ten minutes.

cat cidr-china.txt | awk '/^[^#]/ { print $1 }' | sudo xargs -I {} ufw deny from {} to any

This will take several minutes so be patient. The command will ignore all the lines in the text file that start with # and uses the all the sub-net info to setup blocking rules in your UFW configuration. Please keep the cidr-china.txt because you might need it at some point whenever you decide to remove the blocking rules. This can be done with this command:

cat cidr-china.txt | awk '/^[^#]/ { print $1 }' | sudo xargs -I {} ufw delete deny from {}

You should also perform this command when you decide to ‘update’ the list at some point in the future. So remove everything before importing a new list!

There are many more ways to feed the information in the text file to UFW. Here’s another example where I block all traffic to port 22 originating from China, and allowing all other regular traffic.

cat cidr-china.txt | grep -v ^# | while read subnet; do sudo ufw deny proto tcp from $subnet to any port 22; done

The command to undo all the lines that the previous command added:

cat cidr-china.txt | grep -v ^# | while read subnet; do sudo ufw delete deny proto tcp from $subnet to any port 22; done

Make sure to check the firewall config when you’re done using ufw status.

sudo ufw status

Leave a comment