fail2ban: Configuration error
Every few weeks, I usually check my server:
- Is everything OK with Docker?
docker ps
- Are the backups being created correctly?
borgmatic repo-info
- Are my defenses working?
iptable -n -L
- Are my update automation daemons running?
htop /server-config
This time, however, iptable
showed a blank page on the DOCKER-USEr
chain. This is unusual and indicates that something is wrong with fail2ban.
schallbert@machine:~# iptables -n -L
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-USER all -- 0.0.0.0/0 0.0.0.0/0
DOCKER-FORWARD all -- 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-USER (1 references)
target port opt source destination
The output reads something like
“The
FORWARD
chain forwards, as required by Docker, to the container-relevantDOCKER-USER
chain. However, no applications are listed under this chain that can reject or prohibit packets from being forwarded (REJECT/DROP
).”
Two entries for caddy-server
and caddy-ratelimit
should appear here.
“fail2ban ERROR Failed during configuration”
So I first check Docker:
docker logs -t fail2ban # Print logs for the container named fail2ban with a timestamp
Instead of being rewarded with <timestamp> Server ready
after scrolling through as usual, I see a never-ending flood of log messages. They repeat themselves and show that fail2ban is exiting with Exit with code 255
. I get a better overview of the log if I only print the last 100 lines:
docker logs -t --tail 100 fail2ban # Nur die letzten 100 Zeilen des Logs ausgeben, mit Zeitstempel
The error message
<timestamp, ID> ERROR Failed during configuration: Bad value substitution:
option 'action' in section 'caddy-ratelimit' contains an interpolation key 'banaction' which is not a valid option name.
Raw value: '%(action_)s'
This message is interesting because I had problems with jail.local
at exactly this point when I was creating the article Fail2ban with Caddy. At the time, I had to remove action = iptables-multiport
from the configuration because the triggering IP addresses had landed on the wrong CHAIN
(INPUT).
Now, the default action on the DOCKER-USER
chain seems to no longer work. So, I’m searching a few sources for a possible solution. However, I can’t find any references to updates that would cause major changes in the action.d
folder either in the update history of fail2ban or in the linuxserver.io distribution I’m using.
Solution via banaction = iptables[type=multiport]
So I tried the web search and found a comment from a fail2ban maintainer:
“[…] With action = iptables[type=multiport, protocol=tcp, chain=DOCKER-USER] you overwrote the default action […] [Solution:] simply set the chain variable only in the jail […]:
port = http, https banaction = iptables[type=multiport] chain = DOCKER-USER
”
The basis for this statement can be found in the Docker Docs. Side note: In all places, it is recommended to use the more modern nftables instead of iptables for future applications. Here is an article on the topic.
This allows me to completely delete the action
field that was previously present in my jail.local
and use banaction
instead. It now looks like this:
# jail.local update Oct-2025
# Server/Client errors: 401 403 404 500
[caddy-status]
enabled = true
chain = DOCKER-USER
port = http,https
filter = caddy-status
logpath = <path/to/logfiles>
findtime = 10min
maxretry = 5
bantime = 1d
banaction = iptables[type=multiport]
With this configuration, fail2ban boots normally and displays Server ready
.
Verifying the solution using iptables
As described above, I create entries in the test log files that should trigger the actions of caddy-status
and caddy-ratelimit
. As expected, I get the following in the “blocklist”:
schallbert@machine:~# iptables -n -L
Chain DOCKER-USER (1 references)
target prot opt source destination
f2b-caddy-ratelimit tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443
f2b-caddy-status tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443