====== Blacklist Countries with Shorewall and IPset ====== 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. ====== Geoblock blacklist ====== 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). ====== geoallow whitelist ====== 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 ====== Startup at boot ====== 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 &