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, the target for ssh is, the target for https is 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 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/";

# Change hostname with your external address name.
        { host: ""; port: "443"; }

        { name: "ssh"; service: "ssh"; host: ""; port: "8022"; fork: true;},
        { name: "ssl"; host: ""; port: "443"; log_level: 0; }

My /etc/ipfw/sslh.rules


ipfw add 20000 fwd,443 log tcp from 443 to any out
ipfw add 30000 fwd,443 log tcp from 8022 to any out

My /root/


# based on
# Copyright (c) 2004,2005 RPTN.Net,
# Copyright (c) 2005,
# Copyright (c) 2006 Bob (kba at
# You may use this code under the GPL, version 2 or newer.
# Updates for IPF by
# Copyright (c) 2018 Matt Okeson-Harlow,
# 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


# exclude local network, yoda and leia

# 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}

# 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
        ipfw -q add ${RULE} deny tcp from $ip to any in

I added the following to my /etc/crontab

# sshd-fwscan to block failed logins
*/10    *   *   *   *   root    /root/