Update 30-7-2023 – This post is a bit old. I have written a new article on the subject. Check it out here: https://www.ustoopia.nl/featured/block-countries-based-on-geo-data-with-ufw-firewall/
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 known as UFW, that I already had running can do this easily. If you’re new to UFW, take a look at this very comprehensive page showing how to set it up.
Here are two examples showing how to set up 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 look up 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 picked China.
Save the text file to any location on your server using an 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 subnet info to set up 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.