Guides
Report fail2ban bans to AbuseIPDB
fail2ban can report every address it bans to AbuseIPDB, the shared database of abusive IPs. It's one extra action line per jail. The decisions that matter are which jails to report and what your reports reveal about your server.
To report bans to AbuseIPDB, put your API key in /etc/fail2ban/action.d/abuseipdb.local and add %(action_abuseipdb)s[abuseipdb_category="18,22"] as a second action line in the jail. fail2ban then calls AbuseIPDB's v2 report API with curl on every new ban, sending the IP, the categories and the matched log lines as the comment.
[Init]
abuseipdb_apikey = YOUR_API_KEY[sshd]
enabled = true
maxretry = 5
action = %(action_)s
%(action_abuseipdb)s[abuseipdb_category="18,22"]Step by step#
- Create an AbuseIPDB account and an API key (Account → API). The free plan allows 1,000 checks and reports per day combined.
- Store the key in
/etc/fail2ban/action.d/abuseipdb.localas shown above, and restrict it:sudo chmod 600 /etc/fail2ban/action.d/abuseipdb.local. Keeping the key out ofjail.localmeans you can share your jail config without leaking it. - Make sure
curlis installed. The action is acurl -sSfcall tohttps://api.abuseipdb.com/api/v2/report. - Add the action to the jails you want to report. Keep
%(action_)sas the first line. That's the actual firewall ban. Without it the jail would report but not block. - Reload and check:
sudo fail2ban-client -t && sudo fail2ban-client reload, thensudo fail2ban-client get sshd actionsshould list bothnftables(or your ban action) andabuseipdb.
Setting action in a jail replaces the default action list for that jail only (jail options). The action_abuseipdb shortcut in jail.conf is just the action name, so you pass parameters to it in brackets. The action sets norestored = 1: bans that fail2ban restores from its database after a restart aren't reported a second time.
Categories per jail#
abuseipdb_category is required. AbuseIPDB rejects reports without a category. Use comma-separated IDs, from the list in action.d/abuseipdb.conf:
| Jail | Suggested categories | IDs |
|---|---|---|
sshd |
Brute-Force + SSH | 18,22 |
postfix-sasl, dovecot |
Brute-Force | 18 |
nginx-http-auth, apache-auth, WordPress/app logins |
Brute-Force + Web App Attack | 18,21 |
nginx-botsearch, apache-noscript |
Web App Attack + Bad Web Bot | 21,19 |
postfix (spam rejects) |
Email Spam | 11 |
recidive |
Brute-Force (+ Port Scan if relevant) | 18 or 18,14 |
Other IDs from the list: 4 DDoS Attack, 9 Open Proxy, 10 Web Spam, 20 Exploited Host, 23 IoT Targeted. The full descriptions are on AbuseIPDB's categories page.
[postfix-sasl]
enabled = true
backend = systemd
action = %(action_)s
%(action_abuseipdb)s[abuseipdb_category="18"]
[recidive]
enabled = true
action = %(action_)s
%(action_abuseipdb)s[abuseipdb_category="18"]Which jails should report?#
A report says "this address attacked me". The action file itself (and the fail2ban developers) recommend reporting only when you're confident:
- recidive: the address was banned repeatedly. The best candidate.
- Jails with a high
maxretry, well beyond a user mistyping a password. - Filters that humans rarely trigger: SSH with password login disabled (any failure is a bot), bot-search filters, SASL failures on an MTA with few users.
If you just want to know about bans yourself, email alerts are the private alternative. Don't report from jails that regularly catch your own users, such as webmail or Nextcloud with a low maxretry. A false report against a customer's office IP or a mobile carrier's CGNAT address can get that address blocked elsewhere. And don't report addresses from a misconfigured reverse proxy: if every ban is your proxy's IP, fix that first.
Rate limits#
- Daily quota: the free plan allows 1,000 report and check requests per day. Paid plans allow more. A busy server with several reporting jails can hit 1,000. The API then answers HTTP 429 and
curl -fexits non-zero, so/var/log/fail2ban.logshows a failedabuseipdbaction. The firewall ban itself still works, because it's a separate action. - Same IP once per 15 minutes: reporting an address again within 15 minutes is rejected with 429. It happens when two jails ban the same IP at once. It's harmless, but noisy in the log.
If you hit the daily limit regularly, report only from recidive.
Privacy: what the report contains#
The default action sends the matched log lines (<matches>, cut to 1,000 characters) as the report's comment, and AbuseIPDB shows comments publicly. Depending on the filter, those lines can contain:
- your server's hostname (syslog prefix) and local IP (
lip=in Dovecot lines), - usernames that were tried, which on a mail server are often your real users' addresses,
- request paths, query strings and user agents from web logs.
AbuseIPDB's documentation asks reporters to strip personal data. The simplest fix is to override the ban command with a fixed comment:
[Definition]
actionban = curl -sSf "https://api.abuseipdb.com/api/v2/report" -H "Accept: application/json" -H "Key: <abuseipdb_apikey>" --data-urlencode "comment=fail2ban: <failures> failed logins (jail <name>)" --data "ip=<ip>" --data "categories=<abuseipdb_category>"
[Init]
abuseipdb_apikey = YOUR_API_KEY<failures> and <name> are filled in by fail2ban (failure count and jail name). Check the resulting command with sudo fail2ban-client -d | grep abuseipdb. More tags are listed in custom actions.
Check that reports are sent#
fail2ban only logs action output when something fails, so look in two places:
# errors from the curl call (bad key, 429, network)
sudo grep -i abuseipdb /var/log/fail2ban.log
# your reports, in the AbuseIPDB dashboard (Account → Reports)There's no dry-run mode. The first real ban after a reload is your test: it should appear in your AbuseIPDB reports within seconds, and a wrong key or a quota problem shows up as a failed abuseipdb action in /var/log/fail2ban.log.
blocklist.de#
blocklist.de collects reports and forwards them to the abuse contacts of the attacking networks. Register a server there to get an API key, then:
[DEFAULT]
sender = server-email-registered@example.com
blocklist_de_apikey = YOUR_BLOCKLIST_DE_KEY
[sshd]
enabled = true
action = %(action_)s
%(action_blocklist_de)sThe action sends sender as the server email, so it must match the address you registered. The service name is the jail name. Like AbuseIPDB, it sends the matched log lines and skips restored bans.
IPThreat#
The ipthreat action reports to ipthreat.net. Request an API key with bulk-report permission, put it in /etc/fail2ban/action.d/ipthreat.local under [Init] as ipthreat_apikey = ..., and add ipthreat[] as an extra action line. The defaults report flag 8 (BruteForce) with the jail name as the system. Override them with ipthreat[ipthreat_system="SSH", ipthreat_flags="8"]. It sends only the IP, flags, system and the note "fail2ban", no log lines.
FAQ#
How do I report fail2ban bans to AbuseIPDB?#
Put abuseipdb_apikey = YOUR_KEY under [Init] in /etc/fail2ban/action.d/abuseipdb.local, then add %(action_abuseipdb)s[abuseipdb_category="18,22"] as a second line under action = %(action_)s in the jail. Reload fail2ban. Each new ban is reported with curl to AbuseIPDB's v2 API.
Which AbuseIPDB categories should I use for SSH?#
Use 18,22: 18 is Brute-Force and 22 is SSH. AbuseIPDB recommends combining 22 with a more specific category. For web logins use 18,21 (Web App Attack), for mail authentication 18, and for repeat offenders from recidive 18.
What is the AbuseIPDB rate limit for fail2ban?#
The free plan allows 1,000 check and report requests per day, and the same IP can only be reported once every 15 minutes. Over the limit, the API returns HTTP 429 and fail2ban logs a failed action, but the firewall ban still works. Report from fewer jails, for example only recidive, if you hit it.
Does the fail2ban abuseipdb action share my log lines?#
Yes. By default it sends up to 1,000 characters of matched log lines as the public comment, which can include your hostname, local IP and tried usernames. Override actionban in abuseipdb.local with a fixed comment if you don't want to publish them.
Spotted something wrong or out of date? Tell us — every page is checked against the current fail2ban release.