From a0403b8d000894929c1886c0234cb1a54c8c24a9 Mon Sep 17 00:00:00 2001 From: Debian Date: Thu, 21 May 2026 11:34:48 +0200 Subject: [PATCH] fix(firewall): WireGuard peer-to-peer forward-Chain-Auto-Rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Die forward-chain hatte policy=drop ohne Ausnahme für WireGuard- Peer-to-Peer-Traffic. Pakete von Peer A nach Peer B (beide am selben wg-Interface) müssen durch die Box forwarded werden — das war bisher stiller Drop. Lösung: loadView liest alle aktiven server-mode WG-Interfaces und trägt sie in View.WGServerIfaces ein. Das Template emittiert pro Interface iifname "" accept in der forward-chain. Return-Pakete gehen bereits via ct state established durch. Co-Authored-By: Claude Sonnet 4.6 --- VERSION | 2 +- internal/firewall/firewall.go | 21 +++++++++++++++++++++ internal/firewall/ruleset.nft.tpl | 9 +++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index da44c7f..3baec79 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.50 +1.1.51 diff --git a/internal/firewall/firewall.go b/internal/firewall/firewall.go index b3005b8..0969043 100644 --- a/internal/firewall/firewall.go +++ b/internal/firewall/firewall.go @@ -103,6 +103,14 @@ type View struct { // Operator never edits these — they belong to the service. If // the service is removed/disabled, the rule is gone next render. AutoRules []AutoFWRule + + // WGServerIfaces holds the interface names of all active + // WireGuard server-mode interfaces. The forward chain emits + // iifname "" accept for each — required so that peer-to- + // peer traffic (Peer A → Peer B both connected to the same wg + // interface) can be forwarded by the box. Without this, the + // forward policy=drop silently kills all inter-peer packets. + WGServerIfaces []string } // AutoFWRule is one auto-emitted inbound rule. Proto is "tcp" or @@ -278,6 +286,19 @@ func (g *Generator) loadView(ctx context.Context) (*View, error) { // ── Auto-Rules aus laufender Service-Config ── view.AutoRules = g.loadAutoRules(ctx) + // ── WireGuard server-iface names (für forward-chain) ── + wgRows, err := g.Pool.Query(ctx, + `SELECT name FROM wireguard_interfaces WHERE active AND mode = 'server'`) + if err == nil { + defer wgRows.Close() + for wgRows.Next() { + var name string + if wgRows.Scan(&name) == nil { + view.WGServerIfaces = append(view.WGServerIfaces, name) + } + } + } + return view, nil } diff --git a/internal/firewall/ruleset.nft.tpl b/internal/firewall/ruleset.nft.tpl index 941d2be..4d35bb8 100644 --- a/internal/firewall/ruleset.nft.tpl +++ b/internal/firewall/ruleset.nft.tpl @@ -98,6 +98,15 @@ table inet edgeguard { ip saddr {{.SrcCIDR}} ct state new accept comment "auto-forward for NAT rule {{.ID}}" {{end}}{{end}}{{end}} + # Auto-Forward für WireGuard-Server-Interfaces: Peer-to-Peer- + # Traffic (Peer A → Peer B, beide via dasselbe wg-Interface) + # muss durch die Box forwarded werden. Ohne diese Regel droppt + # policy=drop den Traffic, auch wenn WG ihn korrekt entschlüsselt. + # Return-Pakete gehen bereits via ct state established durch. +{{range .WGServerIfaces}} + iifname "{{.}}" accept comment "auto: WireGuard peer-forward {{.}}" +{{end}} + # Default-Drop-Logging (limit-rated, siehe input-chain). limit rate 10/second log prefix "edgeguard:drop-forward " group 0 }