diff --git a/VERSION b/VERSION index b668c3b..f8f3c08 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.16 +1.0.18 diff --git a/cmd/edgeguard-api/main.go b/cmd/edgeguard-api/main.go index 5e194a8..2015d49 100644 --- a/cmd/edgeguard-api/main.go +++ b/cmd/edgeguard-api/main.go @@ -39,7 +39,7 @@ import ( wgsvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/wireguard" ) -var version = "1.0.16" +var version = "1.0.18" func main() { addr := os.Getenv("EDGEGUARD_API_ADDR") diff --git a/cmd/edgeguard-ctl/main.go b/cmd/edgeguard-ctl/main.go index 33e2dce..70daf2c 100644 --- a/cmd/edgeguard-ctl/main.go +++ b/cmd/edgeguard-ctl/main.go @@ -9,7 +9,7 @@ import ( "os" ) -var version = "1.0.16" +var version = "1.0.18" const usage = `edgeguard-ctl — EdgeGuard CLI diff --git a/cmd/edgeguard-scheduler/main.go b/cmd/edgeguard-scheduler/main.go index bac660d..29898c3 100644 --- a/cmd/edgeguard-scheduler/main.go +++ b/cmd/edgeguard-scheduler/main.go @@ -21,7 +21,7 @@ import ( "git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts" ) -var version = "1.0.16" +var version = "1.0.18" const ( // renewTickInterval — how often we re-evaluate expiring certs. diff --git a/internal/firewall/ruleset.nft.tpl b/internal/firewall/ruleset.nft.tpl index 482494c..9435984 100644 --- a/internal/firewall/ruleset.nft.tpl +++ b/internal/firewall/ruleset.nft.tpl @@ -48,20 +48,14 @@ table inet edgeguard { tcp dport 8443 ip6 saddr @peer_ipv6 accept # ── Operator-defined rules ── -{{- range .Legs}} +{{range .Legs}} # rule {{.RuleID}}{{if .Name}} ({{.Name}}){{end}}{{if .Comment}} — {{.Comment}}{{end}} - {{- if .SrcIfaces}} iifname { {{join .SrcIfaces ", "}} }{{end -}} - {{- if .DstIfaces}} oifname { {{join .DstIfaces ", "}} }{{end -}} - {{- if .SrcAddrs}} ip saddr { {{join .SrcAddrs ", "}} }{{end -}} - {{- if .DstAddrs}} ip daddr { {{join .DstAddrs ", "}} }{{end -}} - {{- with .Service -}} - {{- if and (or (eq .Proto "tcp") (eq .Proto "udp")) .PortStart}} {{.Proto}} dport {{.PortStart}}{{if and .PortEnd (ne .PortEnd .PortStart)}}-{{.PortEnd}}{{end}} - {{- else if eq .Proto "icmp"}} ip protocol icmp - {{- else if eq .Proto "icmpv6"}} ip6 nexthdr icmpv6 - {{- end -}} - {{- end -}} - {{- if .Log}} log prefix "edgeguard:{{.RuleID}} "{{end}} {{.Action}} -{{- end}} + {{- /* Body MUSS auf EIGENER Zeile starten (nicht via {{- }} an + die Comment-Zeile angehängt — sonst frisst nft die rule + als Teil des # Kommentars). */ -}} + {{""}} + {{if .SrcIfaces}}iifname { {{join .SrcIfaces ", "}} } {{end}}{{if .DstIfaces}}oifname { {{join .DstIfaces ", "}} } {{end}}{{if .SrcAddrs}}ip saddr { {{join .SrcAddrs ", "}} } {{end}}{{if .DstAddrs}}ip daddr { {{join .DstAddrs ", "}} } {{end}}{{with .Service}}{{if and (or (eq .Proto "tcp") (eq .Proto "udp")) .PortStart}}{{.Proto}} dport {{.PortStart}}{{if and .PortEnd (ne .PortEnd .PortStart)}}-{{.PortEnd}}{{end}} {{else if eq .Proto "icmp"}}ip protocol icmp {{else if eq .Proto "icmpv6"}}ip6 nexthdr icmpv6 {{end}}{{end}}{{if .Log}}log prefix "edgeguard:{{.RuleID}} " {{end}}{{.Action}} +{{end}} } chain forward { diff --git a/internal/wireguard/wireguard.go b/internal/wireguard/wireguard.go index 330650e..76d8cc8 100644 --- a/internal/wireguard/wireguard.go +++ b/internal/wireguard/wireguard.go @@ -155,6 +155,15 @@ func (g *Generator) renderIface(ctx context.Context, ifc models.WireguardInterfa } path := filepath.Join(ConfDir, ifc.Name+".conf") + // wg-quick@.service liest /etc/wireguard/.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/.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) +} diff --git a/management-ui/package.json b/management-ui/package.json index 9232c0a..806a407 100644 --- a/management-ui/package.json +++ b/management-ui/package.json @@ -1,7 +1,7 @@ { "name": "edgeguard-management-ui", "private": true, - "version": "1.0.16", + "version": "1.0.18", "type": "module", "scripts": { "dev": "vite", diff --git a/management-ui/src/components/Layout/Sidebar.tsx b/management-ui/src/components/Layout/Sidebar.tsx index 6d9b4af..05fb79e 100644 --- a/management-ui/src/components/Layout/Sidebar.tsx +++ b/management-ui/src/components/Layout/Sidebar.tsx @@ -70,7 +70,7 @@ const NAV: NavSection[] = [ }, ] -const VERSION = '1.0.16' +const VERSION = '1.0.18' export default function Sidebar({ isOpen, onClose }: SidebarProps) { const { t } = useTranslation()