For the complete documentation index, see llms.txt. This page is also available as Markdown.

31.6 blocklistd

blocklistd is a daemon: it listens on a socket, receiving notifications from other daemons about connection successes or failures, primarily used to block source addresses that initiate too many connection attempts. A typical scenario is that SSH services on the Internet often receive a large number of requests from bots or scripts attempting to gain access through password guessing. With blocklistd, the daemon can notify the firewall to create filtering rules after a single source address attempts too many connections, thereby blocking excessive connection attempts.

blocklistd was originally developed on NetBSD and released with NetBSD 7, initially named blacklistd. NetBSD renamed it to blocklistd in 2020, and FreeBSD followed suit in 2025. It was introduced from NetBSD starting with FreeBSD 11, where the command and service name remained blacklistd in FreeBSD 11–14, with the configuration file at /etc/blacklistd.conf; starting from FreeBSD 15, it was changed to blocklistd, with the corresponding configuration file at /etc/blocklistd.conf. This section is based on FreeBSD 15's blocklistd; readers using older versions should replace blocklistd in the commands and paths with blacklistd.

This section introduces the usage and examples of blocklistd. Readers should be familiar with basic firewall concepts.

Enabling blocklistd

To enable the daemon at system startup, execute the following command:

# service blocklistd enable

To manually start the service, run the following command:

# service blocklistd start

Creating a blocklistd Rule Set

The blocklistd rule set is located in the /etc/blocklistd.conf file, with one rule per line. Each rule consists of seven fields separated by spaces or tabs. Rules are divided into local and remote, applied to the local machine where blocklistd is running and to external sources, respectively.

Local Rules

The default configuration file /etc/blocklistd.conf contains the following:

# Blocklist rule
# adr/mask:port	type	proto	owner		name	nfail	duration
[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	duration
[remote]
#129.168.0.0/16	*	*	*		=	*	*
#[2001:db8::]/32:ssh	*	*	*		=	*	*
#6161		=	=	=		=/24	=	=
#*		stream	tcp	*		=	=	=

The default local rules in the file /etc/blocklistd.conf are shown below:

All rules after the [local] section are treated as local rules (this is the default setting) and apply to the local machine. When the [remote] section is encountered, subsequent rules are treated as remote rules. Wildcards are represented by an asterisk (*), matching any content in that field.

The seven fields together define a rule, with fields separated by tabs or spaces:

  • adr/mask:port, type, proto, owner: The first four fields identify the traffic to be placed on the block list.

    • adr/mask:port field: Defines the address. In local rules, this field is the network port.

      The syntax for the adr/mask:port address field:

      The adr/mask:port address field can be specified numerically as IPv4 or IPv6 (indicated by square brackets), or using an interface name such as em0.

    • type field: Defines the socket type. TCP sockets are of stream type, while UDP is represented by dgram. Since SSH is based on the TCP protocol, the example above uses stream.

    • proto field: Defines the protocol. Available protocols include tcp, udp, tcp6, udp6, or a numeric protocol number. Unless it is necessary to distinguish traffic by specific protocol, wildcards are typically used as shown in the example to match all protocols.

    • owner field: Defines the effective user or owner of the daemon reporting the event. When a daemon reports an event, this field identifies it. A username or UID can be used here, or a wildcard.

  • name, nfail, duration: The last three fields define blocklistd's behavior.

    • name field: Defines the packet filter rule name, marking the beginning of the rule's behavioral portion. If a separate block list is needed, an anchor name can be used in this field. Otherwise, a wildcard is sufficient. When the name begins with a hyphen (-), it indicates that an anchor with the default rule name should be used. The modified example is as follows:

      Under this rule, new ban rules will be added to the anchor blocklistd-ssh.

      If an entire subnet needs to be blocked because a particular IP violated a rule, a / can be used in the rule name. The part after the / in the name will be treated as a mask, applied to the address specified in the rule. For example, the following rule will block all addresses in the /24 network segment adjacent to the specified address.

      Note

      The correct protocol must be specified here. IPv4 and IPv6 handle /24 differently, so * cannot be used in the third field of this rule.

      This rule defines that if any host in this network violates the rule, all other hosts in the network will also be blocked.

    • nfail field: Sets how many login failures are required before a remote IP is placed on the block list. If a wildcard is used in this position, blocking is never triggered. In the example above, a limit of 3 login failures is defined, meaning that after 3 failed SSH login attempts, the IP is blocked.

  • duration field: Specifies how long a host remains on the block list. The default unit is seconds, but suffixes such as m, h, and d can be specified to indicate minutes, hours, and days, respectively.

The complete example rule ssh stream * * * 3 24h means: after three SSH authentication failures, a new PF blocking rule will be generated for that host. When a rule matches, local rules are checked in order from the most specific (rules with the strictest matching conditions and smallest scope) to the least specific (rules with broad matching conditions and large scope). After a successful match, remote rules are applied, and the matching remote rule modifies the name, nfail, and duration fields.

Remote Rules

remote rules specify how blocklistd adjusts its behavior based on the remote host currently being evaluated. Each field in a remote rule is the same as in a local rule; the only difference is how blocklistd uses these fields. The following explains using example rules:

The address field can be an IP address (IPv4 or IPv6), a port, or both. This allows setting special rules for specific remote address ranges (as shown in this example). The socket type, protocol, and owner fields are interpreted exactly the same as in local rules.

The name field differs: in remote rules, an equals sign (=) indicates that blocklistd uses the value of the name field from the matching local rule. If the name field is written in the format =/XX (such as =/24), the name value is inherited while applying /XX as a mask prefix to the address (i.e., blocking the entire /XX subnet). If only = is used without the / portion, the mask is not modified. A PF anchor name can also be used here, in which case blocklistd adds rules for that address block under the anchor. If a wildcard is used, the default table is used.

The nfail column can define a custom failure count for a specific address. This is useful when setting exceptions for specific rules, such as giving certain users more lenient login attempt opportunities. When the sixth field uses an asterisk, the blocking feature is disabled.

remote rules can impose stricter restrictions compared to login attempts from the local network (such as an office).

Configuring blocklistd Clients

In FreeBSD, several packages can take advantage of blocklistd's functionality. The most commonly used are ftpd(8) and sshd(8), which can block excessive connection attempts.

To enable blocklistd for the SSH daemon, add the following line to the /etc/ssh/sshd_config file:

Then restart sshd for the changes to take effect.

For the Port ftp/freebsd-ftpd, blocklist functionality can be enabled via the -B parameter. This can be set either in /etc/inetd.conf or written as a flag in /etc/rc.conf as follows:

The above is all the configuration needed for these programs to communicate with blocklistd.

Enabling the PF Firewall

blocklistd is only a monitoring daemon and has no blocking capability on its own; it relies on a firewall to enforce blocks. Refer to other sections for installing and enabling the PF firewall. The example uses PF, but other available firewalls on FreeBSD can also work with blocklistd.

blocklistd places all blocking rules under the PF anchor blocklistd in the /etc/pf.conf file. Therefore, the following content needs to be written into the PF firewall configuration file /etc/pf.conf:

Then enable the PF firewall.

Managing blocklistd

blocklistd provides the management tool blocklistctl(8) for viewing addresses and networks blocked by the rules defined in blocklistd.conf(5).

To view the current list of blocked hosts, use the following command:

This example shows that login attempts from the address range 192.168.179.32/32 on port 22 have reached the limit of 3. Since SSH allows clients to make multiple login attempts on a single TCP connection, the actual number of attempts may slightly exceed the configured nfail value. The "last access" column in the output shows the time of the last connection attempt.

Tip

For testing, first save the configuration file /etc/blocklistd.conf to another location, then create a new empty configuration file with the content * * * * * 3 180 (block any connection on any port after three attempts for 180 seconds). Also, blocklistd does not interrupt currently active connections, so relevant connections must be disconnected before testing. Do not perform this test in a production environment!

To view the remaining time a host has on the block list, add the -r parameter to the previous command.

In this example, there are 2 minutes and 13 seconds remaining before the host is unblocked.

Removing a Host from blocklistd

Sometimes it is necessary to remove a host from the block list before the remaining time expires. However, blocklistd itself does not provide this functionality.

However, the pfctl command can be used to remove the address from the PF table. Each blocked port has a sub-anchor under the blocklistd anchor in /etc/pf.conf. For example, the sub-anchor for blocking port 22 is blocklistd/22. Within this sub-anchor, there is a table containing all blocked addresses, with the table name being "port" followed by the port number, which in this case is port22.

With this information, pfctl(8) can be used to display all listed addresses:

After identifying the address to be unbanned from the list, use the following command to remove it:

blocklistd is not aware of changes in PF, so even after the address has been removed from PF, it will still appear in the blocklistctl output. The entry in the blocklistd database will eventually expire and be removed from the output.

If that host matches a blocking rule in blocklistd again, the corresponding entry for that host will be added once more.

Last updated