I run SSH on standard port 22 with fail2ban to prevent brute-force logins. Despite this I am still annoyed by the frequency of fail2ban alerts for countries like China.
<toc><ul><li><link topicref=“2”>Geoblock blacklist</link></li><li><link topicref=“3”>geoallow whitelist</link></li><li><link topicref=“4”>Startup at boot</link></li></ul></toc>
I use a dynamic ipset referenced by shorewall as a blacklist because I have no reason for IPs from certain countries to contact my server.
/usr/local/sbin/ipset-geoblock-country.sh:
#!/bin/bash #Debug # set -x exec 1> >(logger -s -t $(basename $0)) 2>&1 logger "Start: $0" /sbin/ipset create geoblock hash:net -exist /sbin/ipset flush geoblock #for IP in $(/usr/bin/wget -O - http://www.ipdeny.com/ipblocks/data/countries/{ca,us}.zone) for IP in $(/usr/bin/wget -q -O - ftp://ftp.arin.net/pub/stats/apnic/delegated-apnic-latest | awk -F'|' 'BEGIN{OFS=""} ( $2 == "CN" || $2 == "VN" ) && $3 == "ipv4" {print $4,"/",32-(log($5)/log(2))}' | aggregate) do /usr/sbin/ipset -A geoblock $IP -exist done logger "End: $0"
and I symlinked that script into /etc/cron.weekly to add IPs to this ipset (fast lookup) list
cd /etc/cron.weekly ln -s /usr/local/sbin/ipset-geoblock-country.sh .
apt install ipset aggregate chmod u+x /usr/local/sbin/ipset-geoblock-country.sh
Finally I told shorewall to use the ipset as its blacklist, and applied the blacklist to the public interface.
/etc/shorewall/blacklist:
############################################################################### #ADDRESS/SUBNET PROTOCOL PORT OPTIONS +geoblock
/etc/shorewall/interfaces:
#ZONE INTERFACE BROADCAST OPTIONS net eth0 detect tcpflags,nosmurfs,routefilter,logmartians,blacklist
:~# iptables-save | grep geoblock -A blacklst -m set --match-set geoblock src -j DROP
You can use +geoblock in other places in your shorewall configuration to provide a more surgical block or allow (/etc/shorewall/rules).
Here I populated an ipset called geoallow which contains only the countries I want to allow to ssh to my server.
/etc/shorewall/rules:
Ping(ACCEPT) all all ACCEPT net:+geoallow $FW tcp ssh
:~# iptables-save | grep geoallow -A net2fw -p tcp -m tcp --dport 22 -m set --match-set geoallow src -j ACCEPT
It is important to create the ipset (even though its empty) on reboot, or shorewall won't start.
Add the create to /etc/defaults/shorewall or anything that starts before shorewall:
/usr/sbin/ipset -N geoblock nethash
and add the script to /etc/shorewall/started or anything that runs after the network is up:
#!/bin/bash /usr/local/sbin/ipset-geoblock-country.sh &