From b0c29b7caa4bdf68400f7bbb7fc71f5e0c693f02 Mon Sep 17 00:00:00 2001 From: Kuzz007 Date: Tue, 4 Aug 2026 01:35:36 +0300 Subject: [PATCH] feat(amneziawgnet): opt-in verbose device logging via AMNEZIAWGNET_DEBUG The embedded amneziawg-go Device is silent by design (DeviceOptions' Logger defaults to LogLevelSilent) -- real protocol-level diagnostics (handshake progress, decrypt/MAC errors, keepalive state) were completely unavailable while debugging a live "handshake happens, then goes silent" report on a real test box, with nothing useful in the panel's own logs. Setting AMNEZIAWGNET_DEBUG on the host now switches every embedded interface to LogLevelVerbose. Deliberately env-var-gated, not a permanent level bump: this logging has no per-peer filtering, so it's meant for targeted investigation, not routine operation. --- internal/amneziawgnet/manager.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/internal/amneziawgnet/manager.go b/internal/amneziawgnet/manager.go index 9e3c2bf23..94bb09c42 100644 --- a/internal/amneziawgnet/manager.go +++ b/internal/amneziawgnet/manager.go @@ -3,15 +3,34 @@ package amneziawgnet import ( "fmt" "net/netip" + "os" "strings" "sync" + "github.com/amnezia-vpn/amneziawg-go/v3/device" "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet" "github.com/mhsanaei/3x-ui/v3/internal/amneziawg" "github.com/mhsanaei/3x-ui/v3/internal/logger" ) +// verboseLoggerIfEnabled returns a real amneziawg-go verbose logger (real +// handshake/keepalive/decrypt-error diagnostics -- the device is otherwise +// completely silent by design, see DeviceOptions' own doc comment) when the +// AMNEZIAWGNET_DEBUG environment variable is set to any non-empty value, +// nil otherwise (NewDevice's own default -- LogLevelSilent -- applies). +// Deliberately opt-in and env-var-gated rather than a permanent log-level +// setting: this device's own protocol-level logging has no per-peer +// filtering, so enabling it on a busy real inbound would be noisy; it's +// meant for exactly this kind of "why did this one handshake go quiet" +// investigation on a low-traffic box. +func verboseLoggerIfEnabled(inboundID int) *device.Logger { + if os.Getenv("AMNEZIAWGNET_DEBUG") == "" { + return nil + } + return device.NewLogger(device.LogLevelVerbose, fmt.Sprintf("(awg#%d) ", inboundID)) +} + // Desired pairs an amneziawg.Instance (the shared, DB-backed shape // internal/amneziawg's own kernel-module Manager also reconciles toward) // with this package's own embedded-only DeviceOptions -- the AWG 3.0 fields @@ -83,6 +102,9 @@ func (m *Manager) Ensure(d Desired) error { // makes the address/MTU rebuild path worth avoiding too. func (m *Manager) ensureLocked(d Desired) error { inst, opts := d.Instance, d.Options + if opts.Logger == nil { + opts.Logger = verboseLoggerIfEnabled(inst.Id) + } structFP := addressFingerprint(inst) cur, exists := m.ifaces[inst.Id]