Troubleshooting
Nothing is being banned
Is anything being recognised? shield stats shows lines and
hits. Lines climbing with hits at zero means the parsers match nothing:
check the prefilter against a real line, then the pattern.
shieldlist-agent -dry-run 1h
reads the last hour and prints what the rules make of it, enforcing nothing. It is the fastest way to see the whole chain at once.
Is the rule armed? state: test records and sanctions
nothing, on purpose.
Is something exempt? shield why <address> says everything on record
against it. Check exemptions.yaml and exemptions-cli.yaml — the
second is what shield exempt wrote.
Did the agent start after the lines were written? A live tail joins the present: what was already in the file when it started is that file's past. Use Replay.
A ban is not stopping traffic
shield status shows nft_table MISSING if something flushed the
agent's table — another firewall tool, or a nft flush ruleset in a
script. The agent rebuilds it at startup.
unenforced counts sanctions on record that the kernel refused. They are
retried on every round; anything other than zero deserves a look at the
log.
Check the counters are moving:
nft -t list table inet shieldlist
Remember the ban may be port-scoped: a policy with ports: [service]
closes only the ports the parser declared.
The agent looks stuck
shield stats says agent stale with a last_beat when nothing has
written a health snapshot recently.
If it is running and read_lag is large and growing, it is behind, not
stuck — and it says so in the log once, and once again when it catches
up:
WARN falling behind on reads behind=24.9MB rate=68000
INFO caught up on reads
A quiet log is normal. The agent speaks when it decides something and when something is wrong; under a flood it logs bans, not lines.
Memory
shed in shield status counts evidence dropped to stay inside the
ceiling. Non-zero means the rules want to hold more than
limits.memory allows — the log line that goes with it lists the
remedies. See Sizing and limits.
memory_rss far above what you expected on a machine with lots of free
memory is usually the ceiling doing what it was told: half the machine by
default.
The machine is busy and it is not the agent
A kernel worker burning a quarter core with a large set is the kernel
sweeping expired elements. The agent sets gc-interval 1h to keep that
rare; if you see it anyway, check the sets actually carry it:
nft -t list table inet shieldlist
Do not do this
nft list sets — without -t, any listing that reaches the elements
prints all of them. At five million that is more than ten minutes and a
core. Ctrl-C is safe: it is a read, nothing is modified. Use nft -t list sets.
Editing the store by hand. The agent owns it. Use shield unban and
shield exempt, which ask the agent to act rather than writing behind
its back.
Configuration is refused
shieldlist-agent -t
reports every problem at once, each with its file and line. Common ones:
- a parser with no
prefilter— it is mandatory; time_fieldwithouttime_format, or the reverse — both or neither;- a rule naming a parser or policy that does not exist;
- a category read from both a file and a journald unit, which would count everything twice;
- a rule with no positive weight, which could never fire.
Getting the story of one address
shield why 203.0.113.9
Active and past sanctions, the log lines that convicted each, and any range ban covering it without naming it. This is the answer to "why is my customer blocked".