Shieldlist agent — log collection and sanction enforcement on a protected machine
  • Go 97.8%
  • Shell 1.9%
  • Makefile 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-16 17:36:04 +00:00
assets the Shieldlist icon 2026-08-16 16:33:41 +00:00
cmd shield on the fleet: ban, exemptions, unexempt, hits, watched, lists, list, requests, request, reports, report, owners, owner, permissions, accounts, account, api-tokens, api-token, join-tokens, agent resync|revoke, me, vitals, stats, config, updates, geoip, maintenance, prune, vacuum, repair, settings, file, packs, parsers, policies, presets, templates; -json prints the answer itself 2026-10-16 17:36:04 +00:00
config notify is beside the ban, not instead of it; trust require below 1 asks for less evidence; reconnects jittered; a secrets.yaml other users can read is noticed 2026-10-16 17:16:29 +00:00
docs shield on the fleet: ban, exemptions, unexempt, hits, watched, lists, list, requests, request, reports, report, owners, owner, permissions, accounts, account, api-tokens, api-token, join-tokens, agent resync|revoke, me, vitals, stats, config, updates, geoip, maintenance, prune, vacuum, repair, settings, file, packs, parsers, policies, presets, templates; -json prints the answer itself 2026-10-16 17:36:04 +00:00
examples The configuration made simple: one rule, five blocks, every number a value or a level 2026-08-18 08:43:25 +00:00
geoip geoip: Holder — the ASN database's entry filed for an address, its prefix, number and name, in one tree descent 2026-09-26 22:32:49 +00:00
internal notify is beside the ban, not instead of it; trust require below 1 asks for less evidence; reconnects jittered; a secrets.yaml other users can read is noticed 2026-10-16 17:16:29 +00:00
packaging a bare machine is not thirty warnings: one line per kind of log it has none of, the rules reading them idle in one line; init says the service runs; enrol is one command in agent.yaml's comment; CPUAccounting= dropped from the unit (removed in systemd 259) 2026-09-28 14:14:17 +00:00
proto/shieldlist/v1 bans: a ban records what its offender had to reach when the threshold was moved — tightened for a repeat offender, raised for a trusted network — with its earlier bans; shield why says "repeat offender: threshold 15/1m instead of 60/1m" 2026-10-06 00:32:04 +00:00
report Comments say what the code does, not who asked or when 2026-10-14 14:39:46 +00:00
scripts Comments say what the code does, not who asked or when 2026-10-14 14:39:46 +00:00
shipped Comments say what the code does, not who asked or when 2026-10-14 14:39:46 +00:00
testdata/load agent, eval: forget the oldest, say so, and let the operator size it 2026-08-13 14:59:16 +00:00
.gitignore Comments say what the code does, not who asked or when 2026-10-14 14:39:46 +00:00
buf.gen.yaml enrolled mode: the agent talks to its controller 2026-08-15 16:31:36 +00:00
buf.yaml enrolled mode: the agent talks to its controller 2026-08-15 16:31:36 +00:00
CLAUDE.md parse, eval, agent, shield: every rule's cost is measured, warned about, never disarmed 2026-08-14 13:14:09 +00:00
CONTRIBUTING.md The development suite is called dev, not beta 2026-08-26 21:01:20 +00:00
go.mod enrolled mode: the agent talks to its controller 2026-08-15 16:31:36 +00:00
go.sum enrolled mode: the agent talks to its controller 2026-08-15 16:31:36 +00:00
LICENSE Add AGPL-3.0-only licensing 2026-08-06 20:13:39 +00:00
Makefile deb: the binaries carry the package version, build number included — a bare v0.1.0-dev made the controller think every agent too old for its newer keys 2026-10-07 07:00:13 +00:00
README.md docs: the library under /usr/share, shield init, enrol in one command — README and the man page 2026-09-28 11:13:26 +00:00
THIRD_PARTY_LICENSES Man pages (shield.1, shieldlist-agent.8), third-party licence notices (scripts/third-party.sh, shipped), suite beta 2026-08-17 13:47:58 +00:00

shieldlist-agent

The Shieldlist agent runs on a protected machine and defends it on its own: it tails its declared log inputs, evaluates its rules locally, applies sanctions to the machine's nftables, and keeps every decision in a local store that survives restarts. One binary, configured by plain YAML files, no external service on the machine it protects.

The shield CLI ships alongside it: status, stats, bans, why, unban, exempt, replay — aggregate-first, built for a store that can hold millions of bans.

It arrives with the free rule library — SSH, mail, BIND, MariaDB, the web rules that convict on the request itself — and shield init names the logs the machine actually keeps, in detect-only: a machine is watched the evening it is installed, and armed when a person says so.

The same agent enrols to a central controller as an option, never a requirement — standalone is a mode, not a fork. Enrolled (shield enrol -controller URL <join-token>), it receives its parsers, rules, policies and the fleet's exemptions from the controller and applies a new revision in place, takes its state from it, reports every sanction it decides, enforces the fleet's sanctions and the lifts decided centrally. It is one implementation of the agent protocol, which is published from shieldlist-controller as a public API; shield also drives the whole fleet through the controller (-controller URL -token T).

Installing

On Debian and its derivatives, from the APT repository (amd64, arm64, armhf, riscv64):

curl -fsSL https://repo.lrob.net/apt/shieldlist/shieldlist.gpg -o /usr/share/keyrings/shieldlist.gpg
echo "deb [signed-by=/usr/share/keyrings/shieldlist.gpg] https://repo.lrob.net/apt/shieldlist stable main" > /etc/apt/sources.list.d/shieldlist.list
apt update && apt install shieldlist-agent

The repository is signed with the Shieldlist key, fingerprint B528 0C88 7016 8A94 40A9 05C4 3BB5 8113 CFAB 6DC5 (gpg --show-keys shieldlist.gpg); dev in place of stable gets prereleases and development builds. The same .deb files sit on the release page, one per architecture, for apt install ./file.deb.

The package installs shieldlist-agent and shield under /usr/sbin, the rule library under /usr/share/shieldlist-agent, the shieldlist user the agent runs as, the systemd unit, and — on a machine with no agent.yaml yet — runs shield init, which names the logs this machine keeps and enforces nothing; the service is enabled and started. Upgrading (apt install ./newer.deb) restarts the agent, replaces the library and touches no configuration; purging removes the agent's state and configuration, never a co-installed controller's.

Elsewhere, or without packages, the installer script:

curl -fsSLO https://git.lrob.net/Shieldlist/shieldlist-agent/raw/branch/main/scripts/install.sh
less install.sh          # it is one file of sh — read it
sh install.sh

It installs the binaries for this machine's architecture, checks them against the release's SHA256SUMS, and installs the systemd unit; then shield init writes the library from the binary and a first configuration that names the logs it found and enforces nothing: every rule records what it would have done and nftables is never touched. Run it beside whatever already guards the machine, read a day of it with shield status, shield bans and shield why, then set state: on and restart.

Re-running upgrades the binaries and touches no configuration. Nothing is unbanned by a restart: the sets and their timeouts live in the kernel.

make build builds both binaries from source; there is no cgo, so every supported architecture is a plain cross-compile (make dist).

Release signing is not implemented yet — a checksum served from the same host as the binary proves the download was not corrupted and nothing more (SPEC §11).

Documentation

  • Configuration reference: docs/CONFIG.md in shieldlist-controller — the dry-run validator (shieldlist-agent -t) is its ground truth.
  • What the agent costs the machine, and the one limit no setting can bound: docs/RESOURCES.md.
  • The administrator's guide: the wiki.

Third-party software

The binaries link a handful of Go modules, each under its own licence: yaml.v3 (MIT/Apache-2.0), modernc.org/sqlite with libc, mathutil and memory (BSD-3), google.golang.org/protobuf (BSD-3), golang.org/x/sys (BSD-3), github.com/google/uuid (BSD-3), github.com/dustin/go-humanize (MIT), github.com/remyoudompheng/bigfft (BSD-3). Their licence texts are reproduced in THIRD_PARTY_LICENSES (regenerated by make third-party from what is actually linked) and shipped in the packages under /usr/share/doc/shieldlist-agent/. Shieldlist itself is free software under the GNU AGPL v3.

Contributing

See CONTRIBUTING.md.

Credits

An enrolled agent is served the free DB-IP Lite country and ASN databases by its controller — IP Geolocation by DB-IP, CC BY 4.0 — for countries/asns in rules and the origin shown by shield. The rule packs credit their own sources (the CrowdSec hub, Mitchell Krogza's bad-bots list) in the rules repository; the controller's README and wiki carry the full credits.

License

This project is licensed under the GNU Affero General Public License v3.0 — see the LICENSE file.

SPDX identifier: AGPL-3.0-only