From 467d69aa7cd9a3e3dfeee54c626e0b845eabd74a Mon Sep 17 00:00:00 2001 From: Owen Date: Mon, 8 Dec 2025 14:51:13 -0500 Subject: [PATCH 01/11] Fix docker username issue --- .github/workflows/cicd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index bf6dfc5..7d0363d 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -30,7 +30,7 @@ jobs: timeout-minutes: 120 env: # Target images - DOCKERHUB_IMAGE: docker.io/${{ secrets.DOCKER_HUB_USERNAME }}/${{ github.event.repository.name }} + DOCKERHUB_IMAGE: docker.io/fosrl/${{ github.event.repository.name }} GHCR_IMAGE: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }} steps: From b96ee16fbf12d330a648e6b0d619ba044b47e9c9 Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 11 Dec 2025 16:19:08 -0500 Subject: [PATCH 02/11] Add regex to runs on --- .github/workflows/cicd.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 7d0363d..d1c178e 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -14,9 +14,10 @@ permissions: # - COSIGN_PRIVATE_KEY / COSIGN_PASSWORD / COSIGN_PUBLIC_KEY: for key-based signing on: - push: - tags: - - "*" + push: + tags: + - "[0-9]+.[0-9]+.[0-9]+" + - "[0-9]+.[0-9]+.[0-9]+.rc.[0-9]+" concurrency: group: ${{ github.ref }} From 364fa020aa3d2ced1d876a5b91a14219b60ddbd4 Mon Sep 17 00:00:00 2001 From: Owen Date: Fri, 12 Dec 2025 11:47:04 -0500 Subject: [PATCH 03/11] Add healthcheck route --- main.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/main.go b/main.go index 6352b4b..3fe7084 100644 --- a/main.go +++ b/main.go @@ -382,6 +382,7 @@ func main() { http.HandleFunc("/update-proxy-mapping", handleUpdateProxyMapping) http.HandleFunc("/update-destinations", handleUpdateDestinations) http.HandleFunc("/update-local-snis", handleUpdateLocalSNIs) + http.HandleFunc("/healthz", handleHealthz) logger.Info("Starting HTTP server on %s", listenAddr) // HTTP server with graceful shutdown on context cancel @@ -722,6 +723,15 @@ func handlePeer(w http.ResponseWriter, r *http.Request) { } } +func handleHealthz(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte("ok")) +} + func handleAddPeer(w http.ResponseWriter, r *http.Request) { var peer Peer if err := json.NewDecoder(r.Body).Decode(&peer); err != nil { From 5414d21dcd838df26e246204ca031626ad5ce7ce Mon Sep 17 00:00:00 2001 From: Owen Date: Fri, 12 Dec 2025 18:40:33 -0500 Subject: [PATCH 04/11] Quiet normal log message Fixes #2057 --- main.go | 28 ++++++++++++++++++++++++++++ relay/relay.go | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 3fe7084..b0f8ca3 100644 --- a/main.go +++ b/main.go @@ -8,11 +8,15 @@ import ( "flag" "fmt" "io" + "log" "net" "net/http" + _ "net/http/pprof" "os" "os/exec" "os/signal" + "runtime" + "runtime/pprof" "strconv" "strings" "sync" @@ -111,6 +115,8 @@ func parseLogLevel(level string) logger.LogLevel { } func main() { + go monitorMemory(1024 * 1024 * 512) // trigger if memory usage exceeds 512MB + var ( err error wgconfig WgConfig @@ -1171,3 +1177,25 @@ func notifyPeerChange(action, publicKey string) { logger.Warn("Notify server returned non-OK: %s", resp.Status) } } + +func monitorMemory(limit uint64) { + var m runtime.MemStats + for { + runtime.ReadMemStats(&m) + if m.Alloc > limit { + fmt.Printf("Memory spike detected (%d bytes). Dumping profile...\n", m.Alloc) + + f, err := os.Create(fmt.Sprintf("/var/config/heap/heap-spike-%d.pprof", time.Now().Unix())) + if err != nil { + log.Println("could not create profile:", err) + } else { + pprof.WriteHeapProfile(f) + f.Close() + } + + // Wait a while before checking again to avoid spamming profiles + time.Sleep(5 * time.Minute) + } + time.Sleep(5 * time.Second) + } +} diff --git a/relay/relay.go b/relay/relay.go index 59faa4d..2b92363 100644 --- a/relay/relay.go +++ b/relay/relay.go @@ -464,7 +464,7 @@ func (s *UDPProxyServer) handleWireGuardPacket(packet []byte, remoteAddr *net.UD _, err = conn.Write(packet) if err != nil { - logger.Error("Failed to forward handshake initiation: %v", err) + logger.Debug("Failed to forward handshake initiation: %v", err) } } From 060038c29b99249090b5b257fc954ea4346e5955 Mon Sep 17 00:00:00 2001 From: Owen Date: Fri, 12 Dec 2025 22:14:13 -0500 Subject: [PATCH 05/11] Try to fix mem leak --- proxy/proxy.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/proxy/proxy.go b/proxy/proxy.go index 4d27bc4..f29878e 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -758,14 +758,20 @@ func (p *SNIProxy) pipe(clientConn, targetConn net.Conn, clientReader io.Reader) var wg sync.WaitGroup wg.Add(2) + // closeOnce ensures we only close connections once + var closeOnce sync.Once + closeConns := func() { + closeOnce.Do(func() { + // Close both connections to unblock any pending reads + clientConn.Close() + targetConn.Close() + }) + } + // Copy data from client to target (using the buffered reader) go func() { defer wg.Done() - defer func() { - if tcpConn, ok := targetConn.(*net.TCPConn); ok { - tcpConn.CloseWrite() - } - }() + defer closeConns() // Use a large buffer for better performance buf := make([]byte, 32*1024) @@ -778,11 +784,7 @@ func (p *SNIProxy) pipe(clientConn, targetConn net.Conn, clientReader io.Reader) // Copy data from target to client go func() { defer wg.Done() - defer func() { - if tcpConn, ok := clientConn.(*net.TCPConn); ok { - tcpConn.CloseWrite() - } - }() + defer closeConns() // Use a large buffer for better performance buf := make([]byte, 32*1024) From 247c47b27fce428cfd7e87941be34e70fc5f3fbd Mon Sep 17 00:00:00 2001 From: Owen Date: Mon, 19 Jan 2026 17:29:04 -0800 Subject: [PATCH 06/11] We dont really support the config file anymore Ref #30 --- README.md | 8 +++----- config_example.json | 23 ----------------------- main.go | 7 ++++++- 3 files changed, 9 insertions(+), 29 deletions(-) delete mode 100644 config_example.json diff --git a/README.md b/README.md index 11fc3de..85c9693 100644 --- a/README.md +++ b/README.md @@ -42,13 +42,12 @@ In single node (self hosted) Pangolin deployments this can be bypassed by using ## CLI Args +Important: - `reachableAt`: How should the remote server reach Gerbil's API? - `generateAndSaveKeyTo`: Where to save the generated WireGuard private key to persist across restarts. -- `remoteConfig` (optional): Remote config location to HTTP get the JSON based config from. See `example_config.json` -- `config` (optional): Local JSON file path to load config. Used if remote config is not supplied. See `example_config.json` - -Note: You must use either `config` or `remoteConfig` to configure WireGuard. +- `remoteConfig`: Remote config location to HTTP get the JSON based config from. +Others: - `reportBandwidthTo` (optional): **DEPRECATED** - Use `remoteConfig` instead. Remote HTTP endpoint to send peer bandwidth data - `interface` (optional): Name of the WireGuard interface created by Gerbil. Default: `wg0` - `listen` (optional): Port to listen on for HTTP server. Default: `:3004` @@ -66,7 +65,6 @@ Note: You must use either `config` or `remoteConfig` to configure WireGuard. All CLI arguments can also be provided via environment variables: - `INTERFACE`: Name of the WireGuard interface -- `CONFIG`: Path to local configuration file - `REMOTE_CONFIG`: URL of the remote config server - `LISTEN`: Address to listen on for HTTP server - `GENERATE_AND_SAVE_KEY_TO`: Path to save generated private key diff --git a/config_example.json b/config_example.json deleted file mode 100644 index 4b20271..0000000 --- a/config_example.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "privateKey": "kBGTgk7c+zncEEoSnMl+jsLjVh5ZVoL/HwBSQem+d1M=", - "listenPort": 51820, - "ipAddress": "10.0.0.1/24", - "peers": [ - { - "publicKey": "5UzzoeveFVSzuqK3nTMS5bA1jIMs1fQffVQzJ8MXUQM=", - "allowedIps": ["10.0.0.0/28"] - }, - { - "publicKey": "kYrZpuO2NsrFoBh1GMNgkhd1i9Rgtu1rAjbJ7qsfngU=", - "allowedIps": ["10.0.0.16/28"] - }, - { - "publicKey": "1YfPUVr9ZF4zehkbI2BQhCxaRLz+Vtwa4vJwH+mpK0A=", - "allowedIps": ["10.0.0.32/28"] - }, - { - "publicKey": "2/U4oyZ+sai336Dal/yExCphL8AxyqvIxMk4qsUy4iI=", - "allowedIps": ["10.0.0.48/28"] - } - ] -} \ No newline at end of file diff --git a/main.go b/main.go index b0f8ca3..a6309b7 100644 --- a/main.go +++ b/main.go @@ -47,6 +47,7 @@ var ( type WgConfig struct { PrivateKey string `json:"privateKey"` ListenPort int `json:"listenPort"` + RelayPort int `json:"relayPort"` IpAddress string `json:"ipAddress"` Peers []Peer `json:"peers"` } @@ -346,7 +347,11 @@ func main() { }) // Start the UDP proxy server - proxyRelay = relay.NewUDPProxyServer(groupCtx, ":21820", remoteConfigURL, key, reachableAt) + relayPort := wgconfig.RelayPort + if relayPort == 0 { + relayPort = 21820 // in case there is no relay port set, use 21820 + } + proxyRelay = relay.NewUDPProxyServer(groupCtx, fmt.Sprintf(":%d", relayPort), remoteConfigURL, key, reachableAt) err = proxyRelay.Start() if err != nil { logger.Fatal("Failed to start UDP proxy server: %v", err) From 06eb4d4310630969493bec5d0f4a1f308856026d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 22:13:52 +0000 Subject: [PATCH 07/11] Bump actions/setup-go from 6.1.0 to 6.2.0 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.1.0 to 6.2.0. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/4dc6199c7b1a012772edbd06daecab0f50c9053c...7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5) --- updated-dependencies: - dependency-name: actions/setup-go dependency-version: 6.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/cicd.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index d1c178e..b1de835 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -57,7 +57,7 @@ jobs: shell: bash - name: Install Go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version: 1.25 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5581708..77de443 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Set up Go - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version: 1.25 From 3886c1a8c10b97558d83da1ca0434583e4d50738 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 21:27:31 +0000 Subject: [PATCH 08/11] Bump docker/setup-buildx-action from 3.11.1 to 3.12.0 Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3.11.1 to 3.12.0. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/e468171a9de216ec08956ac3ada2f0791b6bd435...8d2750c68a42422c14e847fe6c8ac0403b4cbd6f) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-version: 3.12.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/cicd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index b1de835..49a8579 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -42,7 +42,7 @@ jobs: uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Log in to Docker Hub uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 From 69c13adcdb85a3b4129be5d145562f30afb7ac03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 21:27:04 +0000 Subject: [PATCH 09/11] Bump actions/upload-artifact from 5.0.0 to 6.0.0 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5.0.0 to 6.0.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/330a01c490aca151604b8cf639adc76d48f6c5d4...b7c566a772e6b6bfb58ed0dc250532a479d7789f) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/cicd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 49a8579..4c1aa23 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -155,7 +155,7 @@ jobs: shell: bash - name: Upload artifacts from /bin - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: binaries path: bin/ From 4576a2e8a73f3648dbd2d8bb2fb7433b2b89e59c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 21:23:45 +0000 Subject: [PATCH 10/11] Bump actions/checkout from 6.0.0 to 6.0.1 Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.0 to 6.0.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/1af3b93b6815bc44a9784bd300feb67ff0d1eeb3...8e8c483db84b4bee98b60c0593521ed34d9990e8) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/cicd.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 4c1aa23..0fae5c3 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Set up QEMU uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 77de443..8d2c055 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: runs-on: amd64-runner steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Set up Go uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 From 463a4eea797d9c9daab880ef508c652d828726fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 21:21:35 +0000 Subject: [PATCH 11/11] Bump golang.org/x/crypto in the prod-minor-updates group Bumps the prod-minor-updates group with 1 update: [golang.org/x/crypto](https://github.com/golang/crypto). Updates `golang.org/x/crypto` from 0.45.0 to 0.46.0 - [Commits](https://github.com/golang/crypto/compare/v0.45.0...v0.46.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.46.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index a47ae8b..fb9debb 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,8 @@ go 1.25 require ( github.com/patrickmn/go-cache v2.1.0+incompatible github.com/vishvananda/netlink v1.3.1 - golang.org/x/crypto v0.45.0 + golang.org/x/crypto v0.46.0 + golang.org/x/sync v0.1.0 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 ) @@ -17,7 +18,6 @@ require ( github.com/mdlayher/socket v0.4.1 // indirect github.com/vishvananda/netns v0.0.5 // indirect golang.org/x/net v0.47.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.38.0 // indirect + golang.org/x/sys v0.39.0 // indirect golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b // indirect ) diff --git a/go.sum b/go.sum index 4b4298f..72c7d68 100644 --- a/go.sum +++ b/go.sum @@ -16,16 +16,16 @@ github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b h1:J1CaxgLerRR5lgx3wnr6L04cJFbWoceSK9JWBdglINo= golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b/go.mod h1:tqur9LnfstdR9ep2LaJT4lFUl0EjlHtge+gAjmsHUG4= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=