Back to Integrations

Fail2ban Integration

Escalate Fail2ban bans against IPs that ipinsights.io already knows are bad.

Overview

There are two useful patterns here. (A) Maintain a local Fail2ban jail that bans every IP on the ipinsights.io blocklist outright. (B) Use a custom action on your existing jails that queries the ipinsights.io API at ban-time and applies a longer ban for repeat offenders. We'll set up both.

Prerequisites

  • Fail2ban 0.11+ with iptables, nftables or firewalld backend
  • curl and jq on the host
  • Optional: an ipinsights.io API key (only needed for the live-lookup action below) — see your profile page

Pattern A — Blocklist Tail Jail

Mirror the blocklist locally and have Fail2ban tail the file. A new IP appearing in the file triggers an immediate ban.

/usr/local/bin/ipinsights-mirror.sh:

#!/usr/bin/env bash set -euo pipefail FEED="https://ipinsights.io/downloads/blocklist.txt" DST=/var/log/ipinsights-blocklist.log curl -fsSL --max-time 30 "$FEED" \ | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' \ | awk -v ts="$(date '+%Y-%m-%d %H:%M:%S')" '{ print ts " ipinsights blocklisted IP " $1 }' \ > "$DST"

Schedule it hourly (cron or systemd timer). Then create the filter at /etc/fail2ban/filter.d/ipinsights-blocklist.conf:

[Definition] failregex = ^.*ipinsights blocklisted IP <HOST>\s*$ ignoreregex =

And the jail in /etc/fail2ban/jail.d/ipinsights.local:

[ipinsights-blocklist] enabled = true filter = ipinsights-blocklist logpath = /var/log/ipinsights-blocklist.log maxretry = 1 findtime = 1d bantime = 7d action = %(banaction)s[name=ipinsights, port=all, protocol=all]
sudo fail2ban-client reload

Pattern B — Reputation-Aware Action

Drop in an action that queries ipinsights.io for every IP a jail bans, and escalates the ban if the IP is known-bad. Create /etc/fail2ban/action.d/ipinsights-escalate.conf:

[Definition] actionstart = actionstop = actioncheck = actionban = /usr/local/bin/ipinsights-escalate.sh "<ip>" "<name>" actionunban = [Init]

/usr/local/bin/ipinsights-escalate.sh:

#!/usr/bin/env bash # Re-ban the IP for 30 days if IP Insights confirms it's known-bad. set -euo pipefail IP="$1" JAIL="${2:-default}" KEY_FILE="/etc/fail2ban/ipinsights.key" API="https://ipinsights.io/api/v1/lookup" [ -r "$KEY_FILE" ] || exit 0 API_KEY=$(tr -d '\r\n' < "$KEY_FILE") RESPONSE=$(curl -fsS -m 10 -H "X-API-Key: $API_KEY" "$API?ip=$IP" || true) [ -z "$RESPONSE" ] && exit 0 SCORE=$(jq -r '.data.threat_score // 0' <<<"$RESPONSE") TOR=$(jq -r '.data.is_tor // false' <<<"$RESPONSE") if [ "$TOR" = "true" ] || [ "${SCORE:-0}" -ge 80 ]; then fail2ban-client set "$JAIL" banip "$IP" # ensures it's banned # Re-add with explicit 30d ban via the recidive-style approach fail2ban-client set "$JAIL" unbanip "$IP" >/dev/null 2>&1 || true fail2ban-client set "$JAIL" addbantime 2592000 fail2ban-client set "$JAIL" banip "$IP" logger -t ipinsights "escalated ban for $IP (score=$SCORE tor=$TOR jail=$JAIL)" fi
sudo install -m 0640 /tmp/ipinsights.key /etc/fail2ban/ipinsights.key sudo install -m 0755 /tmp/ipinsights-escalate.sh /usr/local/bin/ipinsights-escalate.sh

Attach to an existing jail by adding the action, for example to sshd:

[sshd] enabled = true action = %(action_)s ipinsights-escalate[name=sshd]
sudo fail2ban-client reload

Verify

sudo fail2ban-client status ipinsights-blocklist sudo fail2ban-client status sshd sudo journalctl -u fail2ban -t ipinsights -n 20

API Key: Pattern A needs no key. Pattern B requires one, stored at /etc/fail2ban/ipinsights.key (root-readable only).

Request Higher API Limit

Running a high-volume Fail2ban deployment? If the default rate limit isn't enough for your environment, submit a request below and we'll review it.

Maximum 5,000 characters.