FreeBSD and Blacklistd

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.

1sudo sysrc sshd_flags="-o UseBlacklist=yes"
2sudo service sshd restart

If pf isn’t already enabled, take a look at the pf primer . Enable pf (don’t start it yet) with

1sudo sysrc pf_enable="YES"
2sudo 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.

2anchor "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.

1sudo service pf start
2sudo service pflog start

Hopefully everything worked properly when you started pf. If you are already running pf, you can simply issue

1sudo 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.

1sudo sysrc blacklistd_enable="YES"
2sudo sysrc blacklistd_flags="-r"

We can now configure blacklistd(8) . By default, it looks like this

 1# $FreeBSD: releng/11.1/etc/blacklistd.conf 301226 2016-06-02 19:06:04Z lidl $
 3# Blacklist rule
 4# adr/mask:port                 type    proto   owner           name    nfail   disable
 6ssh                             stream  *       *               *       3       24h
 7ftp                             stream  *       *               *       3       24h
 8smtp                            stream  *       *               *       3       24h
 9submission                      stream  *       *               *       3       24h
10#6161                           stream  tcp6    christos        *       2       10m
11*                               *       *       *               *       3       60
13# adr/mask:port type            proto   owner           name    nfail   disable
15#                 *       *       *               =       *       *
16#6161                           =       =       =               =/24    =       =
17#*                              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:

2[2001:db8:101:ca7::]/56:ssh   *       *       *       =       *       *

Now that you have blacklistd(8) configured, lets start it up

1sudo 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:

1sudo blacklistctl dump -bw
2                                address/ma:port id      nfail   last access
3   OK      3/3     2018/05/13 01:59:32
4                 OK      3/3     2018/05/13 01:51:34
5                 [2001:db8:101:ca7::1/128]:22   OK      6/3     2018/05/13 02:35:15


We covered blacklisting something. What about whitelisting? We can do that under the [remote] section with something like

1# location      type    proto   owner   name    nfail   duration
310.10.2.20:ssh  *       *       *       *       *       *

This means that, for the ssh port (22), always allow the IP

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

1# adr/mask:port                 type    proto   owner           name    nfail   disable
3ssh                             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:

1for p in 25 465 587 ; do
2    pfctl -a blacklistd/${p} -sr -v 2> /dev/null

You should get output that looks similar to this

1block drop in quick proto tcp from <port587> to any port = submission
2  [ Evaluations: 2638      Packets: 0         Bytes: 0           States: 0     ]
3  [ Inserted: uid 0 pid 1240 State Creations: 0     ]

Lastly, if you need to delete an entry, it would look something like this

1pfctl -a blacklistd/${port} -t port${port} -T delete ${ip}

Footnotes and References