Match source/dest zones on conntrack rules #24

Merged
benvin merged 3 commits from benvin/conntrack-zones into benvin/notrack-raw 2026-10-03 23:44:12 +10:00
Member

Conntrack rules ignored their SOURCE/DEST zones and addresses, so a notrack meant for one zone hit every interface.

  • Match the source zone iif in raw_prerouting and the dest zone oif in raw_output
  • Match SOURCE/DEST addresses as saddr/daddr; negated lists stay one AND-ed match
  • Use raw_output only for an fw source: chain: output with another source and chain: prerouting with an fw source are compile errors, chain: both emits prerouting only
  • Keep omitted SOURCE/DEST global (shorewall - = all), as in stock NOTRACK - - udp 53
  • Reject a prerouting DEST zone (other than fw/all) without an address, since prerouting cannot match oif
  • Skip rules for zones with no interfaces and no address (fail closed)
Conntrack rules ignored their SOURCE/DEST zones and addresses, so a notrack meant for one zone hit every interface. - Match the source zone iif in raw_prerouting and the dest zone oif in raw_output - Match SOURCE/DEST addresses as saddr/daddr; negated lists stay one AND-ed match - Use raw_output only for an fw source: `chain: output` with another source and `chain: prerouting` with an fw source are compile errors, `chain: both` emits prerouting only - Keep omitted SOURCE/DEST global (shorewall `-` = all), as in stock `NOTRACK - - udp 53` - Reject a prerouting DEST zone (other than fw/all) without an address, since prerouting cannot match oif - Skip rules for zones with no interfaces and no address (fail closed)
unkin-agent added 1 commit 2026-10-03 22:56:28 +10:00
Match source/dest zones and addresses on conntrack rules
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
3c5f1cacd4
Author
Member
  • internal/nftables/compiler.go:259 — chain: output/both with a non-fw source (e.g. net -> fw) emits raw_output with no iif/oif at all (src iface dropped, fw dest resolves to ""), i.e. bare udp dport 53 notrack on all fw egress, the exact bug this PR fixes → reject non-fw source on raw_output at compile (or skip that chain for it) instead of emitting an unscoped rule.
  • internal/nftables/compiler.go:230 — default chain only keys off src.Zone == fwZone; chain: output with an interface-less non-fw dest still fails closed, but a non-fw source in output silently ignores the source zone (and its fail-closed check) → validate/skip as above and cover with a test.
  • internal/nftables/compiler_test.go:2420 — no cases for chain: output, chain: both, negated address (!192.0.2.1), sport, or a dest-zone-only rule (dest zone ignored in raw_prerouting) → add them; the both case would currently expose the unscoped raw_output rule.
  • internal/nftables/compiler.go:257 — in raw_prerouting a non-fw, interface-bearing dest zone (net -> lan) is silently dropped (dstIfaces forced to ""), so the rule matches regardless of dest → return an error or document/skip; shorewall's DEST zone is not ignorable here.
- internal/nftables/compiler.go:259 — `chain: output`/`both` with a non-fw source (e.g. `net` -> `fw`) emits raw_output with no iif/oif at all (src iface dropped, fw dest resolves to ""), i.e. bare `udp dport 53 notrack` on all fw egress, the exact bug this PR fixes → reject non-fw source on raw_output at compile (or skip that chain for it) instead of emitting an unscoped rule. - internal/nftables/compiler.go:230 — default chain only keys off `src.Zone == fwZone`; `chain: output` with an interface-less non-fw dest still fails closed, but a non-fw source in output silently ignores the source zone (and its fail-closed check) → validate/skip as above and cover with a test. - internal/nftables/compiler_test.go:2420 — no cases for `chain: output`, `chain: both`, negated address (`!192.0.2.1`), sport, or a dest-zone-only rule (dest zone ignored in raw_prerouting) → add them; the `both` case would currently expose the unscoped raw_output rule. - internal/nftables/compiler.go:257 — in raw_prerouting a non-fw, interface-bearing dest zone (`net -> lan`) is silently dropped (dstIfaces forced to ""), so the rule matches regardless of dest → return an error or document/skip; shorewall's DEST zone is not ignorable here.
unkin-agent added 1 commit 2026-10-03 22:59:16 +10:00
Restrict raw_output to fw sources and reject unmatched prerouting dest zones
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
6af17a4c02
Author
Member
  • internal/nftables/compiler.go:233 — explicit chain: prerouting with an fw source falls through to raw_prerouting with no iif (fw sources have no interface), so the rule matches all inbound/forwarded traffic filtered only by DEST/proto, not fw traffic → reject chain: prerouting with SOURCE fw as a compile error (like the non-fw output case) and add a test.
  • internal/nftables/compiler.go:231 — omitted SOURCE with DEST fw/all (no address) in raw_output (chain: output, or both) resolves to no iif/oif/addr, so it emits an unscoped notrack/drop on all locally generated traffic (and unscoped prerouting for both) → require DEST to scope the rule (zone with interfaces, or an address) when SOURCE is omitted in raw_output, else error; add a test.
- internal/nftables/compiler.go:233 — explicit `chain: prerouting` with an fw source falls through to raw_prerouting with no iif (fw sources have no interface), so the rule matches all inbound/forwarded traffic filtered only by DEST/proto, not fw traffic → reject `chain: prerouting` with SOURCE fw as a compile error (like the non-fw `output` case) and add a test. - internal/nftables/compiler.go:231 — omitted SOURCE with DEST `fw`/`all` (no address) in raw_output (`chain: output`, or `both`) resolves to no iif/oif/addr, so it emits an unscoped notrack/drop on all locally generated traffic (and unscoped prerouting for `both`) → require DEST to scope the rule (zone with interfaces, or an address) when SOURCE is omitted in raw_output, else error; add a test.
unkin-agent added 1 commit 2026-10-03 23:01:33 +10:00
Reject fw source on prerouting conntrack and pin global omitted-zone entries
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
337490d995
Author
Member
  • internal/nftables/compiler.go:~235 (compileConntrack) — an unknown SOURCE/DEST zone (e.g. nte) is not rejected: resolveZoneInterfaces returns [""] for zones absent from cfg.Zones, so the rule compiles global and a typo notracks/drops every interface (fail open, the opposite of what this PR is for) → error on zones not in cfg.Zones (other than fw/all/any), plus a test.
  • internal/nftables/compiler.go:~235 — all!net / all+ exclusions are silently ignored: zoneSpecs keeps the whole string as Zone, which is not in cfg.Zones, so the rule is global and the !net exclusion is dropped → expand via expandZoneRef (or reject exclusions), plus a test.
- internal/nftables/compiler.go:~235 (compileConntrack) — an unknown SOURCE/DEST zone (e.g. `nte`) is not rejected: `resolveZoneInterfaces` returns `[""]` for zones absent from `cfg.Zones`, so the rule compiles global and a typo notracks/drops every interface (fail open, the opposite of what this PR is for) → error on zones not in `cfg.Zones` (other than `fw`/`all`/`any`), plus a test. - internal/nftables/compiler.go:~235 — `all!net` / `all+` exclusions are silently ignored: `zoneSpecs` keeps the whole string as `Zone`, which is not in `cfg.Zones`, so the rule is global and the `!net` exclusion is dropped → expand via `expandZoneRef` (or reject exclusions), plus a test.
benvin merged commit 3c5d23a811 into benvin/notrack-raw 2026-10-03 23:44:12 +10:00
benvin deleted branch benvin/conntrack-zones 2026-10-03 23:44:12 +10:00
Sign in to join this conversation.