Skip to main contentSkip to footer

fail2ban integration

Turn every IP that fail2ban bans on your server into a report to the ReportedIP community blacklist. A small custom action calls the report API on each ban, so your firewall and the community protect each other, the same data also feeds the blacklist feed and the DNS/RBL zone.

You need an API key with the report permission. Create one for free in your dashboard; see Authentication for limits. Report only IPs your own server actually caught.

How fail2ban works (in 30 seconds)

fail2ban watches log files (or the systemd journal). A filter matches attack patterns, a jail counts matches per IP within findtime, and once an IP hits maxretry the jail runs its actions (ban + whatever else you add). We add a second action that reports the banned IP to ReportedIP.

1. Create the report action

Save this as /etc/fail2ban/action.d/reportedip.conf. It POSTs the banned IP, the threat categories and a short comment to the report endpoint on every ban.

conf
# /etc/fail2ban/action.d/reportedip.conf
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = curl -sS -m 10 -X POST "<report_url>" \
              -H "X-Key: <api_key>" \
              --data-urlencode "ip=<ip>" \
              --data-urlencode "categories=<categories>" \
              --data-urlencode "comment=fail2ban <name>: <failures> failed attempts" \
              -o /dev/null || :
actionunban =

[Init]
report_url = https://reportedip.com/wp-json/reportedip/v2/report
api_key    = <your-api-key>
categories = 18,22

Tighten the permissions so the key is not world-readable:

bash
chmod 600 /etc/fail2ban/action.d/reportedip.conf

The tags <ip>, <name> (jail name) and <failures> are filled in by fail2ban; <api_key>, <categories> and <report_url> come from the [Init] block.

2. Enable it on a jail

Add the action to a jail in /etc/fail2ban/jail.local in addition to the normal ban action (%(action_)s), not instead of it:

conf
# /etc/fail2ban/jail.local
[sshd]
enabled = true
action  = %(action_)s
          reportedip

You can override the categories per jail by passing them inline, e.g. reportedip[categories="16,21"] on a web-application jail.

3. Apply and verify

Adding a new action needs a full restart, fail2ban-client reload does not reliably attach it. Use systemctl restart fail2ban, then confirm both actions are loaded.
bash
systemctl restart fail2ban
fail2ban-client get sshd actions
# -> The jail sshd has the following actions:
#    nftables, reportedip

Reading the fail2ban log

fail2ban logs to /var/log/fail2ban.log (or the journal: journalctl -u fail2ban). The lines you care about:

log
2026-05-30 21:56:18 fail2ban.filter  [38760]: INFO    [sshd] Found 203.0.113.45 - 2026-05-30 21:56:18
2026-05-30 21:56:26 fail2ban.actions [38760]: NOTICE  [sshd] Ban 203.0.113.45
2026-05-30 22:06:26 fail2ban.actions [38760]: NOTICE  [sshd] Unban 203.0.113.45
Log lineMeaning
Found <ip>The filter matched one attack attempt. Not yet banned.
Ban <ip>Threshold reached, the jail ran its actions, including the report to ReportedIP.
Unban <ip>bantime elapsed; the firewall rule was removed (no report).
Restore Ban <ip>fail2ban restarted and re-applied a still-active ban.

The report action itself is silent on success (-o /dev/null). To watch reports go out, tail the log while testing, or run the action's curl by hand for one IP, a success returns the new report:

json
{"data":{"ipAddress":"203.0.113.45","abuseConfidencePercentage":39,"reportId":"4316026","aggregated":true}}

Live counters: check your key with curl -H "X-Key: <key>" https://reportedip.com/wp-json/reportedip/v2/verify-key and read limits.dailyReportUsage, or open the dashboard.

Choosing threat categories per jail

Pass the category IDs that match what the jail detects. Common mappings (full list in Threat Categories):

JailcategoriesMeaning
sshd18,22Brute-Force, SSH
postfix-sasl, dovecot11,18Email Spam, Brute-Force
proftpd, vsftpd5FTP Brute-Force
nginx-http-auth, apache-auth18,21Brute-Force, Web App Attack
nginx-badbots, apache-badbots14,19Port Scan, Bad Web Bot
apache-sqli, web exploits16,21SQL Injection, Web App Attack
WordPress / wp-login18,21Brute-Force, Web App Attack
recidive (repeat offenders)15,18Hacking, Brute-Force

The bot jails are the ones that produce false reports: a jail that bans by User-Agent catches a real crawler sooner or later. Before reporting such an address, run it through Bot Verification, which applies the method the crawler operator itself publishes.

Reporting more than one jail

Attach the action to each jail and override the categories inline so each report is accurate:

conf
# /etc/fail2ban/jail.local
[sshd]
enabled = true
action  = %(action_)s
          reportedip[categories="18,22"]

[postfix-sasl]
enabled = true
action  = %(action_)s
          reportedip[categories="11,18"]

[recidive]
enabled = true
action  = %(action_)s
          reportedip[categories="15,18"]

Good practice & safety

  • Only report your own bans. Never report IPs you have not observed attacking your own systems, false reports hurt the dataset (and may get your key suspended).
  • Whitelist your own ranges. Keep ignoreip set for your office/monitoring IPs so you never report yourself.
  • Keep the key private (chmod 600). It is not exposed to attackers, but anyone with the file can submit reports as you. Rotate it from the dashboard if leaked.
  • A failed report never blocks a ban. The || : at the end of actionban means a network hiccup at ReportedIP won't stop fail2ban from banning locally.
  • Sensible thresholds. Very low maxretry on noisy jails can over-report transient clients; the defaults (3–5) are fine.

Troubleshooting

SymptomFix
get <jail> actions shows only the ban actionYou reloaded instead of restarting. Run systemctl restart fail2ban.
unknown smtpd restriction / jail won't startConfig typo in jail.local; check indentation of the continuation line under action.
Reports rejected (HTTP 401/403)Key missing the report permission, or wrong header, it must be X-Key.
HTTP 429 / quotaDaily report limit reached for your plan; see Authentication.
Nothing in the log on banThe report action is silent on success. Confirm with fail2ban-client get <jail> actions and a manual curl.
Want to also block using community data? Import the blacklist feed into nftables/ipset, or for mail servers query the DNS/RBL zone.

Last updated: · Maintained by the ReportedIP team

Security Focused
GDPR Compliant
Made in Germany
Back to Docs