3 Troubleshooting
Robin edited this page 2026-08-22 23:15:50 +00:00

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_field without time_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".