fix(firewall+wg): Operator-Rule landete als Comment + wg-quick las falsche Conf
Zwei show-stopper beim Cutover .101 → .6 entdeckt + behoben:
1. nft-Template-Bug: {{- if ...}}-Whitespace-Trimmer nach der
'# rule N' Kommentarzeile schluckte den Newline → die ganze
Operator-Rule landete als Teil des # Kommentars. nft akzeptierte
die Datei (legaler Comment) und der Operator sah keine Wirkung.
Fix: Body auf eigener Zeile via {{""}}-Padding, Trimmer raus.
2. wg-Renderer schrieb /etc/edgeguard/wireguard/<iface>.conf, aber
wg-quick@<iface>.service liest /etc/wireguard/<iface>.conf
(Distro-Default). Die zwei Files driftet auseinander — beim
Restart sah wg-quick die alte AllowedIPs. Fix: Renderer legt
einen Symlink /etc/wireguard/<iface>.conf → /etc/edgeguard/...
beim Render an (idempotent, ersetzt vorhandene Real-Files).
Beide Fixes waren voraussetzung für den .101 → .6 Cutover, der
jetzt sauber läuft: VIP .100 lebt auf .6, Unify Home dial't durch
zu wg7 (handshake), 10.0.10.x via wg7-Tunnel reachable.
Version 1.0.18.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -155,6 +155,15 @@ func (g *Generator) renderIface(ctx context.Context, ifc models.WireguardInterfa
|
||||
}
|
||||
|
||||
path := filepath.Join(ConfDir, ifc.Name+".conf")
|
||||
// wg-quick@<iface>.service liest /etc/wireguard/<iface>.conf (Distro-
|
||||
// Default), nicht unseren ConfDir. Wir lassen die Quelle of truth in
|
||||
// /etc/edgeguard/wireguard/ und symlinken einmalig — sonst lesen
|
||||
// wg-quick und unser Renderer aus zwei verschiedenen Files und
|
||||
// driften auseinander (gefangen 2026-05-10 als wg-quick beim restart
|
||||
// noch alte AllowedIPs aus /etc/wireguard/wg7.conf gelesen hat).
|
||||
if err := ensureWGQuickSymlink(ifc.Name, path); err != nil {
|
||||
return fmt.Errorf("symlink: %w", err)
|
||||
}
|
||||
if existing, err := os.ReadFile(path); err == nil && bytes.Equal(existing, body.Bytes()) {
|
||||
return startWGQuick(ifc.Name)
|
||||
}
|
||||
@@ -163,3 +172,20 @@ func (g *Generator) renderIface(ctx context.Context, ifc models.WireguardInterfa
|
||||
}
|
||||
return restartWGQuick(ifc.Name)
|
||||
}
|
||||
|
||||
// ensureWGQuickSymlink puts /etc/wireguard/<iface>.conf as a symlink
|
||||
// pointing at our managed file in /etc/edgeguard/wireguard/. Idempotent
|
||||
// — if the symlink already targets the right path we no-op; if the
|
||||
// distro path holds a real (legacy) file we replace it.
|
||||
func ensureWGQuickSymlink(iface, target string) error {
|
||||
wgDir := "/etc/wireguard"
|
||||
if err := os.MkdirAll(wgDir, 0o700); err != nil {
|
||||
return err
|
||||
}
|
||||
link := filepath.Join(wgDir, iface+".conf")
|
||||
if cur, err := os.Readlink(link); err == nil && cur == target {
|
||||
return nil
|
||||
}
|
||||
_ = os.Remove(link)
|
||||
return os.Symlink(target, link)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user