> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/ask/flat/chapter-31-firewalls/di-31.5-jie-fail2ban-ji-yu-ipfw-pf-yu-ipf.md).

# 31.5 Fail2Ban (Based on IPFW, PF, and IPF)

In network security practice, brute-force attacks are one of the common threats against authentication systems.

Fail2Ban is a log-based Intrusion Prevention System (IPS) that implements adaptive access control by dynamically updating firewall rules, providing real-time protection for servers.

According to the [official description](https://github.com/fail2ban/fail2ban), Fail2Ban denies new connections from IP addresses with multiple authentication failures by updating system firewall rules (see [How Fail2Ban Works](https://github.com/fail2ban/fail2ban/wiki/How-fail2ban-works)). Fail2Ban is implemented almost entirely in Python (approximately 96% Python code). This section adapts the three common firewalls on FreeBSD (IPFW, PF, and IPF). There is no need to configure all firewalls simultaneously; just choose one of them.

## Installing Fail2Ban

The installation process for Fail2Ban is as follows. Users can choose to install via pkg or Ports.

* Install using pkg:

```sh
# pkg install security/py-fail2ban
```

* Or install using Ports:

```sh
# cd /usr/ports/security/py-fail2ban/
# make install clean
```

After installation, the service must be enabled to start automatically at boot.

* Enable the fail2ban service:

```sh
# service fail2ban enable
```

## Viewing Post-Installation Notes for Fail2Ban

After installation, the following command can be used to view the configuration notes provided by the package.

```sh
# pkg info -D security/py-fail2ban
```

## Fail2Ban Configuration Guide

The following explains the configuration of Fail2Ban.

> **Note**
>
> The term `jail` here does not refer to a BSD system jail (container). In Fail2Ban, a jail is a monitoring and banning configuration unit for a specific service, where each jail corresponds to a service that needs protection (such as SSH, FTP, etc.).

Fail2Ban's workflow consists of two parts: filters parse logs to identify failed login attempts, and actions invoke firewall rules to execute bans.

The related file structure:

```sh
/usr/local/etc/fail2ban/
├── jail.conf
├── filter.d/
│   ├── bsd-sendmail.conf
│   ├── bsd-sshd.conf
│   ├── bsdftp.conf
│   ├── courier-auth.conf
│   ├── mssql-auth.conf
│   ├── murmur.conf
│   ├── mysqld-auth.conf
│   ├── nginx-botsearch.conf
│   ├── slapd.conf
│   ├── softethervpn.conf
│   ├── sogo-auth.conf
│   └── sshd.conf
├── action.d/
│   ├── bsd-ipfw.conf
│   ├── ipfw.conf
│   └── ipfilter.conf
└── jail.d/
    └── sshd.conf
```

The configuration file example is the **/usr/local/etc/fail2ban/jail.conf** file (do not edit it directly, see the notes above). Below only the content needed for this book is listed:

```ini
# DEFAULT is the global definition, after which each jail can individually override these settings.

[DEFAULT]

# "ignoreip" can be a single IP address, CIDR subnet, or DNS hostname list. Fail2Ban
# will not ban hosts matching the list. Multiple addresses can be separated by spaces or commas
# "ignoreip" is the whitelist
# ignoreip = 127.0.0.1/8 ::1

# "maxretry" default retry count
maxretry = 5

# If a host generates "maxretry" failures within the past "findtime" seconds, the host will be banned.
# This is the time window for ban detection.
findtime = 10m

# "bantime" indicates the duration a host is banned, can be an integer in seconds or time abbreviation format (m for minutes, h for hours, d for days, w for weeks, mo for months, y for years)
# This is the ban duration.
bantime  = 10m

[sshd]
# enabled = true
#
# See jail.conf(5)

# "filter" defines the filter used by the jail. ①
# By default, the jail name matches its filter name.
#
filter = %(__name__)s[mode=%(mode)s]
# For example:
# filter = sshd[mode=aggressive]
#
# Action shortcuts. Used to define action parameters.

# Fail2Ban also requires a firewall to execute ban actions.
# Default ban action (e.g., iptables, iptables-new, iptables-multiport, shorewall, etc.). ②
# It is used to define action_* variables, which can be overridden in the global or specific sections of the jail.local file.
# banaction = iptables-multiport
# banaction_allports = iptables-allports
```

* ① List Fail2Ban filter options:

```sh
# ls /usr/local/etc/fail2ban/filter.d/
...some output omitted...
bsd-sendmail.conf		mssql-auth.conf			slapd.conf
bsd-sshd.conf			murmur.conf			softethervpn.conf
bsdftp.conf			mysqld-auth.conf		sogo-auth.conf
courier-auth.conf		nginx-botsearch.conf		sshd.conf
```

Note that files starting with `bsd-` (such as `bsd-sshd.conf`) are variants provided by the FreeBSD Port maintainer for specific environment adaptation, but since `sshd.conf` has better compatibility with the standard Fail2Ban configuration, it should be used directly in this section.

* ② View firewalls supported by Fail2Ban:

```sh
# ls /usr/local/etc/fail2ban/action.d/
bsd-ipfw.conf					ipfw.conf				ipfilter.conf				pf.conf
...other firewalls omitted...
```

## Fail2Ban Ban Configuration

Create and edit the file **/usr/local/etc/fail2ban/jail.d/sshd.conf** with the following content:

```ini
[DEFAULT]
ignoreip=192.168.0.0/24
maxretry = 3
findtime = 10m
bantime = 8h

[sshd]
enabled=true
filter=sshd
action=bsd-ipfw
```

> **Tip**
>
> The `192.168.0.0/24` in the above example is a placeholder and must be replaced with the actual value.

Configuration notes:

* Whitelist, indicating IP ranges that will not be banned. **192.168.0.0/24** represents the range from **192.168.0.0** to **192.168.0.255**.
* `bsd-ipfw` is the example firewall; you can choose your own, see below.

In FreeBSD, Fail2Ban provides two IPFW-related action configurations: `ipfw` and `bsd-ipfw`. The `bsd-ipfw` version is specifically optimized for FreeBSD and has better integration with the system.

> **Warning**
>
> If using the IPFW firewall, you must choose `bsd-ipfw` instead of `ipfw`, otherwise it will not take effect.

## Configuring the Firewall

After completing the Fail2Ban configuration, the corresponding firewall must also be configured, and then the service started.

Start the Fail2Ban service:

```sh
# service fail2ban start
```

### IPFW

IPFW is the built-in firewall for FreeBSD. The Fail2Ban configuration is the same as above.

#### Configuring the Service to Start at Boot

Enable the firewall for automatic startup at boot:

```sh
# sysrc firewall_enable="YES"
```

> **Warning**
>
> Do not execute the `start` command immediately, as this may prevent SSH connections.

#### Modifying the Default IPFW Rule

The default policy of IPFW rules is "default deny," meaning rule 65535 blocks all unmatched traffic. To avoid being locked out during configuration, you can first change it to "default allow":

```sh
# echo 'net.inet.ip.fw.default_to_accept=1' >> /boot/loader.conf   # Set firewall default policy to accept, takes effect at boot
# reboot # Reboot for changes to take effect
```

* Display the current IPFW firewall rule list:

```sh
# ipfw list
...some output omitted...
65535 allow ip from any to any
```

#### References

* FreeBSD Project. ipfw(8) - IP firewall and traffic shaper control program\[EB/OL]. \[2026-03-26]. <https://man.freebsd.org/cgi/man.cgi?query=ipfw&sektion=8>. Official FreeBSD firewall management tool reference manual, providing complete IPFW command documentation.
* dapeng.li. fail2ban\[EB/OL]. \[2026-03-26]. <https://dapeng.li/learning/fail2ban/d4.html>. This section's architecture is based on this, which is a Fail2Ban and FreeBSD integration solution.
* FreeBSD Project. Chapter 33. Firewalls\[EB/OL]. \[2026-04-14]. <https://docs.freebsd.org/en/books/handbook/firewalls/>. FreeBSD Handbook firewall chapter, introducing basic configuration for PF, IPFW, and IPFILTER.
* FreeBSD Foundation. FreeBSD's Firewall Feast\[EB/OL]. \[2026-04-14]. <https://freebsdfoundation.org/wp-content/uploads/2017/06/FreeBSDs-Firewall-Feast.pdf>. Firewall comparison technical article published by the FreeBSD Foundation.

### PF

PF (Packet Filter) is a firewall originating from OpenBSD, configured as follows.

In PF, tables are used to store lists of IP addresses that need to be banned, and anchors are used to organize and manage specific rule sets. Fail2Ban adds IP addresses to PF's table, then applies corresponding rules through anchors to enforce bans.

#### Fail2Ban Configuration File

Change `action=bsd-ipfw` in the configuration file **/usr/local/etc/fail2ban/jail.d/sshd.conf** above to `action=pf[port={22 23}, name=ssh]`. No other configuration items need to be modified.

#### Modifying the PF Configuration File

The PF configuration file must be prepared first. The related directory structure:

```sh
/
├── etc
│   ├── pf.conf
│   ├── ipf.rules
│   └── ipnat.rules
├── usr
│   └── share
│       └── examples
│           ├── pf
│           │   └── pf.conf
│           └── ipfilter
│               ├── ipf.conf.sample
│               └── ipnat.conf.sample
├── var
│   └── log
│       ├── auth.log
│       └── fail2ban.log
└── boot
    └── loader.conf.local
```

* For PF to start properly, copy the sample PF configuration file to the **/etc** directory for modification and use:

```sh
# cp /usr/share/examples/pf/pf.conf /etc/
```

* Edit the **/etc/pf.conf** file and write:

```ini
table <f2b> persist   # Define and persist table f2b
anchor "f2b/*"        # Create and reference f2b-related anchor
block drop in log quick on em0 from <f2b> to any   # Quickly block and log all traffic from the f2b table on the em0 interface
```

* `em0`: The `em0` in the example is the network interface name and must be changed according to the actual network interface. You can use the `ifconfig` command to check.

#### Service

The PF service startup and configuration are as follows.

```sh
# kldload pf # Load kernel module, no need to manually load again afterwards
# service pf enable # Enable at boot
# service pf start # Start the PF firewall
```

**References**

* Xavier Humbert. PF - fail2ban does not feed pf table\[EB/OL]. \[2026-03-26]. <https://forums.freebsd.org/threads/fail2ban-does-not-feed-pf-table.67798/>. FreeBSD community forum discussion on Fail2Ban and PF integration issues.
* mfechner. Fail2ban on FreeBSD drops complete pf firewall rules\[EB/OL]. \[2026-03-26]. <https://github.com/fail2ban/fail2ban/issues/1915>. GitHub Issue documenting Fail2Ban and PF rule conflict issues.

### IPFILTER (IPF)

IPFILTER (IPF) is an open-source firewall, configured as follows.

#### Fail2Ban Configuration File

The `ipfilter` action invokes IPF commands to add and remove ban rules, so change `action=bsd-ipfw` in the configuration file **/usr/local/etc/fail2ban/jail.d/sshd.conf** above to `action=ipfilter`. No other configuration items need to be modified.

#### Service

The IPF service configuration and startup are as follows.

* For IPF to start and work properly, copy the sample file as the default configuration rule set file (the rules included in the sample file do not affect usage):

```sh
# cp /usr/share/examples/ipfilter/ipf.conf.sample /etc/ipf.rules   # Copy the sample ipfilter configuration file to /etc/ipf.rules for modification and use
```

* Configure the daemon:

```sh
# service ipfilter enable   # Set ipfilter service to start automatically at boot
# service ipfilter start    # Start the ipfilter firewall service
```

## Testing the Effect

After configuration is complete, you can test whether Fail2Ban can properly ban IPs. Use the Fail2Ban client to manually add an IP to the ban list to verify functionality.

* To see the effect, use the Fail2Ban client to add IP **192.168.179.1** to the ban list under sshd monitoring:

```sh
# fail2ban-client set sshd banip 192.168.179.1
```

* TTY output: This output shows that the SSH service detected multiple authentication failures from **192.168.179.1**.

```sh
Mar 25 15:27:38 gkla sshd[970]: error : maximum authentication attempts exceeded for ykla from 192.168.179.1 port 8652 ssh2 [ preauth ]
```

Established SSH connections will also be forcibly disconnected.

### Viewing Status

You can view the running status of Fail2Ban with the following command.

View the status of Fail2Ban's sshd monitoring, including the list of banned IPs:

```sh
# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed:	1
|  |- Total failed:	4
|  `- File list:	/var/log/auth.log
`- Actions
   |- Currently banned:	1
   |- Total banned:	1
   `- Banned IP list:	192.168.179.1
```

### Unbanning an IP

If you need to unban a specific IP, you can perform the following operation.

Unban the specified IP from sshd monitoring:

```sh
# fail2ban-client set sshd unbanip 192.168.179.1
1
# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed:	1
|  |- Total failed:	4
|  `- File list:	/var/log/auth.log
`- Actions
   |- Currently banned:	0
   |- Total banned:	1
   `- Banned IP list:
```

## Troubleshooting and Remaining Issues

If you encounter problems, you can check the logs for troubleshooting.

* Fail2Ban logs are located in the **/var/log/fail2ban.log** file.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.bsdcn.org/ask/flat/chapter-31-firewalls/di-31.5-jie-fail2ban-ji-yu-ipfw-pf-yu-ipf.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
