Blocking IPs for failed ssh logins to jails on FreeBSD
I recently got sslh working on my home FreeBSD server. What made this more complicated is that I wanted ssh to go to one jail and https to go to a different jail.
My jail host is 172.27.1.2, the target for ssh is 172.27.1.4, the target for https is 172.27.1.5. The https jail runs a reverse nginx proxy to forward to various other jails and devices on my home network.
Something that I used to use on linux hosts was fail2ban to block the constant brute force ssh attempts against my system. This time around I decided to try something a little simpler. I found this wiki article describing how to use ipfw and a cron job to update a blocklist.
I had to configure ssh on 172.27.1.4 listen on both 22 and 8022, if I tried to just use 22 I could not reach that jail from my local network.
Below are the pieces that make this all work.
My /usr/local/etc/sslh.conf
# This is a basic configuration file that should provide # sensible values for "standard" setup. verbose: false; foreground: false; inetd: false; numeric: false; transparent: true; timeout: 2; user: "root"; pidfile: "/var/run/sslh.pid"; # Change hostname with your external address name. listen: ( { host: "172.27.1.2"; port: "443"; } ); protocols: ( { name: "ssh"; service: "ssh"; host: "172.27.1.4"; port: "8022"; fork: true;}, { name: "ssl"; host: "172.27.1.5"; port: "443"; log_level: 0; } );
My /etc/ipfw/sslh.rules
#!/bin/sh ipfw add 20000 fwd 172.27.1.2,443 log tcp from 172.27.1.5 443 to any out ipfw add 30000 fwd 172.27.1.2,443 log tcp from 172.27.1.4 8022 to any out
My /root/sshd-fwscan.sh
#!/bin/sh # based on http://www.freebsdwiki.net/index.php/Block_repeated_illegal_or_failed_SSH_logins # Copyright (c) 2004,2005 RPTN.Net, # Copyright (c) 2005 DaveG.ca, # Copyright (c) 2006 Bob (kba at ats32.ru) # You may use this code under the GPL, version 2 or newer. # Updates for IPF by Sasha.by # Copyright (c) 2018 Matt Okeson-Harlow, https://technomage.net # 2018-04-29 # changed rule number to 10000 to not impact sslh rules at 20000 # exclude 172.27.1 as that is the home network # exclude remote hosts that I control # lowered the count to 3 from 5 # use find to locate auth.log.*.bz2 files modified in the last 2 days PATH=/bin:/usr/bin:/sbin:/usr/sbin LOGDIR=/usr/jails/kotilo/var/log RULE=10000 # exclude local network, yoda and leia EXCLUDE='172[.]27[.]1|71[.]19[.]155[.]130|71[.]19[.]157[.]86' # log the current rules before we clear them ipfw show ${RULE} | logger -p local0.notice -t sshd-fwscan # clear the current rules if ipfw show | awk '{print $1}' | grep -q ${RULE} ; then ipfw delete ${RULE} fi # This catches repeated attempts for both legal and illegal users # No check for duplicate entries is performed, since the rule # has been deleted. (find ${LOGDIR} -mmin -$((60*24*2)) -name "auth.log.*.bz2" -exec bzcat {} \;; cat ${LOGDIR}/auth.log) | awk '/sshd/ && (/Invalid user/ || /authentication error/) {try[$(NF)]++} END {for (h in try) if (try[h] > 3) print h}' | egrep -v ${EXCLUDE} | while read ip do ipfw -q add ${RULE} deny tcp from $ip to any in done
I added the following to my /etc/crontab
# # sshd-fwscan to block failed logins */10 * * * * root /root/sshd-fwscan.sh