AbuseTrack × CrowdSec integration

CrowdSec detects and blocks attacks locally; AbuseTrack is a community database of abusive IPs, domains and more. The integration connects them in both directions. You can report the IPs CrowdSec bans back to the AbuseTrack community, consume the AbuseTrack blocklist inside CrowdSec so your bouncers block known-bad IPs, or do both. Pick whichever direction fits, or run both on the same host.

Before you start

Direction 1 — report the bans CrowdSec makes

Every IP CrowdSec bans locally (WordPress brute force, scanners, CVE probes and so on) is reported to your AbuseTrack account through the public API. It is report-only: it never touches your firewall or CrowdSec decisions, and it only reports origin: crowdsec detections, so IPs you pulled from the community blocklist are never reported back — no feedback loop.

Create an API key, then run the installer as root:

curl -fsSL https://abusetrack.io/integrations/crowdsec/install.sh | \
  AT_API_KEY=your_api_key AT_API_URL=https://abusetrack.io bash

What the installer does

Scenario → threat-type mapping

The reporter maps CrowdSec scenarios to AbuseTrack threat types so reports are categorised correctly:

CrowdSec scenarioReported as
bf, brute, wordpress_bfBrute Force
scan, probing, crawl, user-agent, proxyPort Scan
wpconfig, env-access, git-config, backupData Theft
cve, rce, exploit, log4j, sqliMalware
anything elseAT_THREAT_DEFAULT (Port Scan)

Want to see what would be sent without sending anything? Run a dry run:

AT_DRY_RUN=1 /usr/local/bin/abusetrack-crowdsec-report

Direction 2 — consume the community blocklist

Use the abusive IPs the community reported to AbuseTrack as a blocklist in CrowdSec. Every IP that enough people flagged becomes a CrowdSec decision and gets blocked by your bouncers, on top of CrowdSec's own scenarios. The feed lives at /api/v1/blocklist.txt — plain text, one IP per line, authenticated with your API key. Quick test:

curl -fsSL -H "Authorization: Bearer your_api_key" \
  "https://abusetrack.io/api/v1/blocklist.txt?score=60&reporters=2&comments=0"

Tuning the feed

Query parameters let you trade coverage for precision. Use comments=0 so the # header is omitted for cscli import:

ParamDefaultMeaning
score25Minimum community risk score, 0–100 (25 = Medium and up)
reporters1Require at least this many distinct reporters
since(off)Only IPs reported within the last N days
limit10000Maximum number of IPs
comments10 returns pure IPs with no # header (for cscli import)

Import into CrowdSec via cron

The simplest, version-agnostic method pulls the feed and imports it as ban decisions. Add this to /etc/cron.d/abusetrack-blocklist:

*/30 * * * * root curl -fsSL -H "Authorization: Bearer YOUR_API_KEY" \
  "https://abusetrack.io/api/v1/blocklist.txt?score=60&reporters=2&comments=0" \
  -o /tmp/abusetrack.txt && cscli decisions import -i /tmp/abusetrack.txt \
  --format values --duration 36h --reason "AbuseTrack community blocklist"

Poll every 15–30 minutes, not every few seconds. The feed is cached for 5 minutes and counts as one API call per refresh against your daily quota, so a 30-minute cron uses about 48 calls a day — far under any tier. Set --duration a little longer than your poll interval so entries refresh before they expire. If you use the CrowdSec Console, you can instead subscribe to the same feed URL under Blocklists → Add a custom blocklist; no cron needed.

Verify

Confirm the imported decisions are active:

cscli decisions list | grep AbuseTrack    # imported bans
cscli decisions list -o json | head       # full detail

Good to know

The feed only consumes AbuseTrack data, and private, loopback and reserved ranges are never reportable, so they never appear in it. Running both directions on one host gives you a closed loop: your server defends itself with CrowdSec, contributes the attacks it sees back to the community, and benefits from what everyone else reports.

See all integrations Read the API documentation fail2ban guide