Linux fail2ban Setup
Introduction
fail2ban is a tool to monitor http requests and activate ip firewall based on a config
How I use it
On my domain I monitor for 403 http codes if this is found then the IP is blocked for a configurable amount to time. We need to -Install fail2ban (just use apt) -Make a filter -Make/Append jail.local -Restart -Monitoring
Make a filter
To make a filter you pointer you create a file in /etc/fail2ban/filters.d. In this case we look for 403 errors and extract the remote host
[Definition]
failregex = ^.*"remote_ip":\s*"<HOST>".*"status":\s*403
datepattern = "ts": {UNIX_TIMESTAMP}
ignoreregex =
Make/Append jail.local
If it exists append to /etc/fail2ban/jail.local
[caddy-json]
enabled = true
filter = caddy-json
port = http,https
logpath = /var/log/caddy/caddy_blah.access.log
maxretry = 5
findtime = 600
bantime = 3600
Restart
sudo systemctl restart fail2ban
The robot mucked mine up the first time through but you can check with
sudo fail2ban-regex /var/log/caddy/access.json /etc/fail2ban/filter.d/caddy-json.conf
Once all working you can list bans with
fail2ban-client status caddy-json
This shows
Status for the jail: caddy-json
|- Filter
| |- Currently failed: 0
| |- Total failed: 26
| `- File list: /var/log/caddy/caddy_blah.access.log
`- Actions
|- Currently banned: 0
|- Total banned: 1
`- Banned IP list:
To remove a ban you can do the following (replace the IP you fool)
sudo fail2ban-client set caddy-json unbanip 10.10.10.10
Monitoring
Like most things you can send metrics to prometheous. Make a script to extract the metric /usr/local/bin/fail2ban_metrics.sh
#!/bin/bash
echo "# HELP fail2ban_banned_total Number of banned IPs per jail"
echo "# TYPE fail2ban_banned_total gauge"
# Get list of jails
#jails=$(fail2ban-client status | grep 'Jail list:' | sed 's/.*Jail list:\s*//g' | tr ',' ' ')
jails=$(fail2ban-client status | awk -F': *' '/Jail list:/ {print $2}' | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
# Loop through each jail and get banned count
#for jail in $jails; do
# banned=$(fail2ban-client status "$jail" | grep 'Currently banned' | awk '{print $NF}')
# echo "fail2ban_banned_total{jail=\"$jail\"} $banned"
#done
for jail in $jails; do
banned=$(fail2ban-client status "$jail" 2>/dev/null | grep 'Currently banned' | awk '{print $NF}')
if [[ "$banned" =~ ^[0-9]+$ ]]; then
echo "fail2ban_banned_total{jail=\"$jail\"} $banned"
else
echo "fail2ban_banned_total{jail=\"$jail\"} 0"
fi
done
Stick it in the cron tab and check with prometheus that it is being processed.
curl -u admin:notsaying-k --cacert /etc/prometheus/yourcert.crt "https://localhost:9090/api/v1/query?query=fail2ban_banned_total" |jq