What is blacklistd(8)?
Its similar to fail2ban, but built-in to FreeBSD. Can we integrate it with our favorite firewall (pf(8))? Of course! What about sshd(5) support? Already handled. What if we want to do the opposite of blacklist? Can we whitelist something? Yes! Lets see how:
blacklistd setup
Start by configuring sshd(8) with blacklistd(8) support. This is just adding a flag to the start options.
sudo sysrc sshd_flags="-o UseBlacklist=yes"
sudo service sshd restart
If pf isn’t already enabled, take a look at the pf primer. Enable pf (don’t start it yet) with
sudo sysrc pf_enable="YES"
sudo sysrc pflog_enable="YES"
If you haven’t defined your external interface in pf.conf(8), do that. In addition, at the top of your block rules, add the anchor line for blacklistd(8). Use the correct interface.
ExtIf="lagg0"
anchor "blacklistd/*" in on $ExtIf
Time to start pf. If you’re connected via ssh(8), you’ll get disconnected. You may wish to run the commands under tmux(1). Make sure you have a way into the host in case your firewall rules aren’t configured properly.
sudo service pf start
sudo service pflog start
Hopefully everything worked properly when you started pf. If you are already running pf, you can simply issue
sudo service pf reload
We want to keep block rules in place after a reboot (these hosts were
blocked for a reason, right?). Use the -r
option for blacklistd_flags
.
sudo sysrc blacklistd_enable="YES"
sudo sysrc blacklistd_flags="-r"
We can now configure blacklistd(8). By default, it looks like this
# $FreeBSD: releng/11.1/etc/blacklistd.conf 301226 2016-06-02 19:06:04Z lidl $
#
# Blacklist rule
# adr/mask:port type proto owner name nfail disable
[local]
ssh stream * * * 3 24h
ftp stream * * * 3 24h
smtp stream * * * 3 24h
submission stream * * * 3 24h
#6161 stream tcp6 christos * 2 10m
* * * * * 3 60
# adr/mask:port type proto owner name nfail disable
[remote]
#129.168.0.0/16 * * * = * *
#6161 = = = =/24 = =
#* stream tcp * = = =
The two most important things to keep straight are [local]
and
[remote]
. [local]
stanza entries are for services you are trying to
protect (ssh, ftp, smtp, etc). [remote]
stanza entries are for how you
wish to treat blocks of IPs (for IPv4, /32 or bigger, for IPv6, /128 or
bigger).
Once you’ve decided which you want to use, you can look at the fields that you will need to fill in. This is a similar structure to the inetd.conf(8) structure.
The notably missing example is IPv6 (why is IPv6 always forgotten in the examples?). If you want to do an IPv6 entry, it looks like this:
[remote]
[2001:db8:101:ca7::]/56:ssh * * * = * *
Now that you have blacklistd(8) configured, lets start it up
sudo service blacklistd start
Check the blocked hosts list
You can use the command blacklistctl dump
to check what host is
blocked. I use two options to show everything for IPv4 and IPv6:
sudo blacklistctl dump -bw
address/ma:port id nfail last access
10.10.2.20/32:22 OK 3/3 2018/05/13 01:59:32
192.168.123.234/32:22 OK 3/3 2018/05/13 01:51:34
[2001:db8:101:ca7::1/128]:22 OK 6/3 2018/05/13 02:35:15
Whitelist
We covered blacklisting something. What about whitelisting? We can do
that under the [remote]
section with something like
# location type proto owner name nfail duration
[remote]
10.10.2.20:ssh * * * * * *
This means that, for the ssh port (22), always allow the IP 10.10.2.20
.
You could do the same thing for a service by moving the entry to the
[local]
section, and removing the IP. This would make it such that any
IP could connect to the ssh port and it would never get blocked by
blacklistd. That would look like this
# adr/mask:port type proto owner name nfail disable
[local]
ssh stream * * * * *
Postfix Support
Recently (Feb, 2018), Postfix got patched to support blacklistd(8). No config changes necessary, just enable support when you build Postfix.
If you want to examine the entries related to postfix, you can run a loop over the external mail ports:
for p in 25 465 587 ; do
pfctl -a blacklistd/${p} -sr -v 2> /dev/null
done
You should get output that looks similar to this
block drop in quick proto tcp from <port587> to any port = submission
[ Evaluations: 2638 Packets: 0 Bytes: 0 States: 0 ]
[ Inserted: uid 0 pid 1240 State Creations: 0 ]
Lastly, if you need to delete an entry, it would look something like this
pfctl -a blacklistd/${port} -t port${port} -T delete ${ip}