Geo-blocking as a security function for port 80 and port 443 on the Raspberry Pi

Since my Allsky camera has been publicly accessible via its own subdomain, I regularly see access attempts from certain countries. IPs from Russia (RU) and China (CN) in particular appear disproportionately often in the log files – mostly automated scanners, bots or credential stuffing attempts.

Of course, a hardened system (firewall, Fail2Ban, rate limits, HTTPS) already provides pretty good protection. But: I wouldn’t have to pull many of these requests into my system in the first place. That’s why I also use geo-blocking: the Raspberry Pi simply rejects TCP connections from certain countries before the web server reaches them.

What geo-blocking does – and doesn’t do

Geo-blocking is not a replacement for a firewall, but it is a useful addition. It prevents: constant port scans from known botnet hotspots, automated web scanners and pointless connections from regions from which no real visitors are guaranteed to come This method is not perfect, of course: anyone using a VPN often appears as “EU” or “USA”. However, it works perfectly for the majority of automated requests.

Technical basis: ipset + iptables

With `ipset` and `iptables`, Linux offers high-performance tools for efficiently blocking large netlists. Ready-made IPv4 and IPv6 lists exist for each country and are updated regularly. As an example, I am blocking: CN (China) and RU (Russia) Other countries such as Indonesia, Thailand etc. can be added at any time. Important for me: Under no circumstances do I want to block one of Letsencrypt’s update servers – because it takes care of my SSL certificate.

Step 1: Install ipset

sudo apt update
sudo apt install ipset

Step 2: Create IP set for the blocked countries

sudo ipset create geoblock hash:net family inet

Step 3: Load country lists for Russia and China

# China (CN)
wget -O - https://www.ipdeny.com/ipblocks/data/countries/cn.zone \
  | sudo xargs -I{} ipset add geoblock {}

# Russia (RU)
wget -O - https://www.ipdeny.com/ipblocks/data/countries/ru.zone \
  | sudo xargs -I{} ipset add geoblock {}

This means that `geoblock` now contains hundreds of network areas that Linux can process extremely efficiently.

Step 4: Set up firewall rules (port 80 and 443)

sudo iptables -I INPUT -p tcp --dport 80 \
  -m set --match-set geoblock src \
  -m conntrack --ctstate NEW -j DROP

sudo iptables -I INPUT -p tcp --dport 443 \
  -m set --match-set geoblock src \
  -m conntrack --ctstate NEW -j DROP

New HTTP or HTTPS connections from Russia and China are completely rejected.

Step 5: Save configuration persistently

sudo apt install netfilter-persistent
sudo netfilter-persistent save

Result: The web server remains clean

Since the activation, significantly fewer requests have landed in my Apache logs and Fail2Ban has had less work to do. The typical bot load from Russia and China has almost completely disappeared.

Optional: Block IPv6 as well

IPv6 networks can also be blocked in the same way as IPv4:

sudo ipset create geoblock6 hash:net family inet6

wget -O - https://www.ipdeny.com/ipv6/ipaddresses/blocks/cn.zone \
  | sudo xargs -I{} ipset add geoblock6 {}

wget -O - https://www.ipdeny.com/ipv6/ipaddresses/blocks/ru.zone \
  | sudo xargs -I{} ipset add geoblock6 {}

sudo ip6tables -I INPUT -p tcp --dport 80 -m set --match-set geoblock6 src -m conntrack --ctstate NEW -j DROP
sudo ip6tables -I INPUT -p tcp --dport 443 -m set --match-set geoblock6 src -m conntrack --ctstate NEW -j DROP

sudo netfilter-persistent save

Done!

Geo-blocking is not a panacea – but it is a very efficient method to reduce the background noise of illegal access. For my Allsky project, it is an additional protection mechanism that is super-easy to implement.

Enjoyed this post?

You can support allsky-rodgau.de with a small coffee on BuyMeACoffee.

Buy me a coffee!