82 lines
5.3 KiB
Markdown
82 lines
5.3 KiB
Markdown
---
|
|
topic: the mesh
|
|
status: accepted
|
|
date: 2026-10-02
|
|
deciders: jochen
|
|
reconstructed: false
|
|
extends: 02-DECISIONS/0179-the-intrusion-seat-serves-its-verbs-and-every-door-declares-its-jail.md
|
|
---
|
|
|
|
# 186. A ban list never holds a neighbour, and the mesh's own bans are its own wherever they hang
|
|
|
|
## Context
|
|
|
|
[ADR 0179](0179-the-intrusion-seat-serves-its-verbs-and-every-door-declares-its-jail.md) gave the
|
|
public proxy a jail. Within the hour the home server's ban list held `192.168.1.1` — the house's own
|
|
router. The router reflects local traffic, so every client in the building reaches that machine as
|
|
the gateway's address; one local request for a name the mesh does not serve, three times in a day,
|
|
and the whole house is refused by the machine it was asking. The jails inherited an `ignoreip` of
|
|
the loopback and the mesh's own range, which was right when the only jail read the ssh daemon and
|
|
the only clients were the mesh's; a jail on a public front door sees the neighbours too.
|
|
|
|
The same jail broke the other half of [ADR 0168](0168-a-converged-machine-is-filtered-by-the-mesh-alone.md).
|
|
The home server began reading *NOT the mesh alone: 1 rule set the mesh did not write refuses traffic
|
|
here*, and the rule set named was the mesh's own ban chain, written by the mesh's own intrusion
|
|
prevention minutes earlier. The host's reader of the legacy filter required every path into a chain
|
|
of refusals to come from a built-in chain whose policy accepts, before it would call that chain a
|
|
ban. On that machine the chain hangs off the container runtime's user chain as well as the input
|
|
chain, and the runtime had set the forward policy to DROP — so the mesh reported its own work as a
|
|
foreigner's, on the one machine where the group's exit condition was supposed to hold.
|
|
|
|
Both faults are one mistake in two places: a rule written about the public internet, applied to
|
|
everything that arrives.
|
|
|
|
## Decision
|
|
|
|
**1. A ban list never holds a neighbour.** The jails the mesh composes never ban a source on a
|
|
private range — the mesh's own range, which was already named rather than written
|
|
([ADR 0112](0112-a-module-definition-names-no-node-mesh-or-path.md)), and every address space
|
|
reserved for private use beside it, in both families. A machine behind a router that reflects local
|
|
traffic sees its whole building as one address; a ban there is a self-inflicted outage, and the
|
|
sources worth banning are not on those ranges in the first place.
|
|
|
|
**2. The mesh's own bans are its own wherever they hang.** A chain of refusals is a ban list when
|
|
every refusal names the sources it refuses and the chain accepts nothing — the rule the host already
|
|
applied to the packet filter's own tables, now applied to the legacy filter too, and nothing more.
|
|
The policy of the chains that jump into it says nothing about what it is: that policy is already
|
|
classified where it belongs, as the container runtime's, and requiring it here counted it twice.
|
|
|
|
**3. A chain that accepts anything is still not a ban.** That is what keeps a predecessor's
|
|
allow-these-and-drop-the-rest chain classified as something an operator must look at, which is the
|
|
distinction [ADR 0168](0168-a-converged-machine-is-filtered-by-the-mesh-alone.md) exists to draw.
|
|
|
|
## Consequences
|
|
|
|
- The composed jails gain the private ranges in their never-ban list. An address already banned
|
|
stays banned until it is released; the house's router was released by hand the moment it was found.
|
|
- The home server reads *the mesh alone* again, which is group 7's exit condition and was false for
|
|
about an hour.
|
|
- A machine whose apply fails for an unrelated reason does not revisit its found firewall's record
|
|
at all — the step runs only after a clean apply ([ADR 0168](0168-a-converged-machine-is-filtered-by-the-mesh-alone.md)).
|
|
The home server's record therefore still reads *retired by the mesh* although the front end is
|
|
uninstalled, and will correct itself once that machine's own stuck module is fixed. It is a stale
|
|
record, not a wrong machine.
|
|
- The record number the front end's removal was given moved under it: another session took 0175
|
|
while that record was in review, and it is now
|
|
[ADR 0180](0180-the-found-front-end-is-uninstalled-once-a-machine-is-converged.md). The citations
|
|
the host and the control plane print were pointing at an unrelated record and are corrected here.
|
|
|
|
## How this is checked
|
|
|
|
| Rule | Checked by |
|
|
|---|---|
|
|
| A private source is never banned | the module's jail configuration, read back by `fail2ban.fail2ban_settings` on a machine |
|
|
| The mesh's own ban chain reads as a ban behind a dropping forward policy | a host test over the home server's own captured rule set |
|
|
| A chain that accepts anything is not a ban | a host test |
|
|
| Live | done 2026-10-02: all four machines read *the mesh alone*, the home server counting its own ban chain as a ban; no ban held anywhere is a private address |
|
|
|
|
## References
|
|
|
|
- [ADR 0179](0179-the-intrusion-seat-serves-its-verbs-and-every-door-declares-its-jail.md), [ADR 0168](0168-a-converged-machine-is-filtered-by-the-mesh-alone.md), [ADR 0112](0112-a-module-definition-names-no-node-mesh-or-path.md), [ADR 0180](0180-the-found-front-end-is-uninstalled-once-a-machine-is-converged.md)
|
|
- [Design 08 — Connectivity](../03-DESIGN/01-to-be/08-connectivity.md), [Design 31 — A module declares its fail2ban jail](../03-DESIGN/01-to-be/31-a-module-declares-its-fail2ban-jail.md)
|