Files
hacks/ipabusedb-docker-reporter
sneak bce9d01142 ipabusedb-docker-reporter: pin docker CLI image, add make push, fix stale names
Pin the docker:cli source to 29.9.3 plus its manifest list digest, tag
the image as git.eeqj.de/sneak/ipabusedb-docker-reporter with the date
and latest, add a push target, and rename the remaining
ipabusedb-docker-ssh references in the README and package doc.
2026-11-06 20:32:16 -08:00
..

ipabusedb-docker-reporter

Reads the logs of a dockerised sshd with docker logs -t, extracts brute-force / invalid-user login attempts, and emits a CSV in the format expected by the AbuseIPDB bulk-report endpoint. Optionally submits it.

What gets reported:

  • Invalid user X from IP port N
  • User X from IP not allowed because not listed in AllowUsers
  • Failed password for invalid user X from IP port N
  • Connection closed by invalid user X IP port N and Disconnected from invalid user X IP port N

Attempts with the username git are excluded (so people poking a git host with git@ are not reported). Private, loopback and link-local source addresses are skipped. Each IP appears once in the CSV, dated with its most recent attempt and annotated with the number of matching lines. Categories are 18,22 (Brute-Force, SSH).

Configuration

A .env file in the working directory is loaded at startup (see .env.example; .env is gitignored). Variables already set in the shell take precedence over the file.

Variable Purpose
DOCKER_CONTAINER_NAME container whose logs are read (required)
IPABUSEDB_API_KEY AbuseIPDB API key (required only with --submit)
DOCKER_HOST passed through to the docker CLI to target a remote daemon

Because the program shells out to the docker CLI with its own environment, DOCKER_HOST (and DOCKER_CONTEXT, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH) work exactly as they do for docker itself. Set DOCKER_HOST=ssh://user@host in .env to read logs from a remote daemon while the AbuseIPDB key never leaves the local machine.

Flags:

Flag Purpose
--since 24h only consider lines newer than now minus this duration
-o FILE write the CSV to FILE instead of stdout
--input FILE parse FILE (or - for stdin) instead of docker logs
--submit POST the CSV to the AbuseIPDB bulk-report endpoint
--env FILE env file to autoload (default .env; missing is ignored)

Usage

$ make build
$ export DOCKER_CONTAINER_NAME=sshd IPABUSEDB_API_KEY=...
$ ./ipabusedb-docker-reporter --since 24h -o reports.csv
$ ./ipabusedb-docker-reporter --since 24h --submit

Submitting manually with curl instead of --submit:

$ ./ipabusedb-docker-reporter --since 24h > reports.csv && curl https://api.abuseipdb.com/api/v2/bulk-report -F csv=@reports.csv -H "Key: $IPABUSEDB_API_KEY"

Running as a container

The Dockerfile builds on git.eeqj.de/sneak/baseimage and installs the program as a runit service (sv/ipabusedb-docker-reporter/run) that sleeps INTERVAL seconds, then runs the reporter with --since ${INTERVAL}s --submit, and repeats. The docker CLI is copied in from the official docker CLI image (pinned by tag and digest in the Dockerfile) so the program can read logs through the host's docker socket.

Variable Purpose
DOCKER_CONTAINER_NAME container whose logs are read (required)
IPABUSEDB_API_KEY AbuseIPDB API key (required)
INTERVAL seconds between runs, and the report window (1200)

make image builds the image, tagged locally as ipabusedb-docker-reporter and as git.eeqj.de/sneak/ipabusedb-docker-reporter with today's date and latest. make push builds and pushes both registry tags (log in once with docker login git.eeqj.de).

$ make push
$ docker run -d --restart unless-stopped \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -e DOCKER_CONTAINER_NAME=sshd \
    -e IPABUSEDB_API_KEY=... \
    -e INTERVAL=1200 \
    git.eeqj.de/sneak/ipabusedb-docker-reporter:latest

Each run's CSV and the AbuseIPDB response go to the container log. If a required variable is missing the service logs an error, sleeps a minute and exits so runit can retry.

make check runs vet, the tests and the build. loglines_example.txt holds sample docker logs -t output used by the tests; example_parser_script.py is the reference script from AbuseIPDB that this program replaces.