make push builds linux/amd64 and linux/arm64 natively, each on a daemon of that arch (amd64 on fsn1app1 via DOCKER_HOST, arm64 locally), pushes the per-arch tags, and joins them into the dated and latest manifest lists with docker buildx imagetools, mirroring the baseimage repo.
109 lines
4.8 KiB
Markdown
109 lines
4.8 KiB
Markdown
# 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](https://www.abuseipdb.com/bulk-report). 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 a local image tagged `ipabusedb-docker-reporter` for
|
|
this machine's architecture. `make push` builds `linux/amd64` and
|
|
`linux/arm64` natively, each on a daemon of that architecture (arm64 on
|
|
the local daemon, amd64 on `fsn1app1` via `DOCKER_HOST`; override
|
|
`DOCKER_HOST_amd64` and `DOCKER_HOST_arm64` on the command line), pushes
|
|
the per-arch tags, and joins them into
|
|
`git.eeqj.de/sneak/ipabusedb-docker-reporter` tagged with today's UTC date
|
|
and `latest`. Log in once with `docker login git.eeqj.de`; the client
|
|
forwards the credentials to the remote daemon.
|
|
|
|
```
|
|
$ 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.
|