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.