fail2ban + Caddy with JSON logs

English
, ,

Hi!

I’m running Caddy and saving access logs to disk in the JSON format. I want to integrate fail2ban to block bots trying /wp-login.php and other known URLs, and I couldn’t find much about how to make fail2ban read Caddy’s logs.

This is a hack that I quickly came up with, barely tested, but I managed to make it work:

/etc/fail2ban/filter.d/caddy-forbidden.local:

1
2
3
4
[Definition]
failregex = "client_ip":"<HOST>"(.*)"status":403
datepattern = "ts":<DATE>\.
ignoreregex =

Append to /etc/fail2ban/jail.local:

1
2
3
4
[caddy-forbidden]
port = http,https
logpath = /var/log/caddy/*.log
enabled = true

So an entry like this will successfully match and ban the IP 192.0.2.6:

1
{"level":"info","ts":1694328885.166141,"logger":"http.log.access.log2","msg":"handled request","request":{"remote_ip":"192.0.2.6","remote_port":"64305","client_ip":"192.0.2.6","proto":"HTTP/1.1","method":"GET","host":"www.kassner.com.br","uri":"/wp-login.php","headers":{...},"tls":{...}},...,"status":403,...}

Lastly, I’ve added to my Caddyfile:

1
2
3
(common) {
        error /wp-login.php "Forbidden" 403
}


It’s worth noting this isn’t well tested, and given there is user input in the logs, you might ran into false-positives with a well-crafted URL or headers. Use at your own risk.

Thank you.