From 9348842e2cd1cc9eea29e43c9ad5cd7740c15309 Mon Sep 17 00:00:00 2001 From: Wouter van Elten Date: Tue, 1 Jul 2025 17:26:49 +0200 Subject: [PATCH 01/22] added use of hostname if available --- docker/client.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docker/client.go b/docker/client.go index 6a3bdb7..226e099 100644 --- a/docker/client.go +++ b/docker/client.go @@ -26,6 +26,8 @@ type Container struct { Labels map[string]string `json:"labels"` Created int64 `json:"created"` Networks map[string]Network `json:"networks"` + Hostname string `json:"hostname"` // added to use hostname if available instead of network address + } // Port represents a port mapping for a Docker container @@ -173,6 +175,14 @@ func ListContainers(socketPath string, enforceNetworkValidation bool) ([]Contain // Short ID like docker ps shortId := c.ID[:12] + // Inspect container to get hostname + hostname := "" + containerInfo, err := cli.ContainerInspect(ctx, c.ID) + if err == nil && containerInfo.Config != nil { + hostname = containerInfo.Config.Hostname + } + + // Skip host container if set if hostContainerId != "" && c.ID == hostContainerId { continue @@ -238,6 +248,7 @@ func ListContainers(socketPath string, enforceNetworkValidation bool) ([]Contain Labels: c.Labels, Created: c.Created, Networks: networks, + Hostname: hostname, // added } dockerContainers = append(dockerContainers, dockerContainer) From a896291831150be4a9dd09c82d423cbc3a4cdbbb Mon Sep 17 00:00:00 2001 From: Wouter van Elten Date: Tue, 1 Jul 2025 17:38:54 +0200 Subject: [PATCH 02/22] Update go.mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 7e2fa2d..c2a2171 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa golang.org/x/net v0.41.0 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 - golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 + golang.zx2c4.com/wireguard/wgctrl v0.0.0-20231211153847-12269c276173 gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 software.sslmate.com/src/go-pkcs12 v0.5.0 ) From 2ecf3297cdd2a73648a0304603d405c9bca466c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Jul 2025 09:36:37 +0000 Subject: [PATCH 03/22] Bump github.com/docker/docker in the prod-patch-updates group Bumps the prod-patch-updates group with 1 update: [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/docker` from 28.3.0+incompatible to 28.3.1+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v28.3.0...v28.3.1) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-version: 28.3.1+incompatible dependency-type: direct:production update-type: version-update:semver-patch dependency-group: prod-patch-updates ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 19ab518..b6c3839 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.1 toolchain go1.23.2 require ( - github.com/docker/docker v28.3.0+incompatible + github.com/docker/docker v28.3.1+incompatible github.com/gorilla/websocket v1.5.3 golang.org/x/net v0.41.0 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 diff --git a/go.sum b/go.sum index 7a98889..e074360 100644 --- a/go.sum +++ b/go.sum @@ -15,8 +15,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.3.0+incompatible h1:ffS62aKWupCWdvcee7nBU9fhnmknOqDPaJAMtfK0ImQ= -github.com/docker/docker v28.3.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.3.1+incompatible h1:20+BmuA9FXlCX4ByQ0vYJcUEnOmRM6XljDnFWR+jCyY= +github.com/docker/docker v28.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= From c2a326c70aa570496232d8f05129a9f5813dc740 Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 3 Jul 2025 09:05:09 -0700 Subject: [PATCH 04/22] Working packages? --- go.mod | 4 ++-- go.sum | 67 ++++++++++++++++++++++++++++++---------------------------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/go.mod b/go.mod index c2a2171..b1dcba5 100644 --- a/go.mod +++ b/go.mod @@ -5,15 +5,14 @@ go 1.23.1 toolchain go1.23.2 require ( - github.com/google/gopacket v1.1.19 github.com/docker/docker v28.3.0+incompatible + github.com/google/gopacket v1.1.19 github.com/gorilla/websocket v1.5.3 github.com/vishvananda/netlink v1.3.0 golang.org/x/crypto v0.39.0 golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa golang.org/x/net v0.41.0 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 - golang.zx2c4.com/wireguard/wgctrl v0.0.0-20231211153847-12269c276173 gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 software.sslmate.com/src/go-pkcs12 v0.5.0 ) @@ -56,4 +55,5 @@ require ( golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.30.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect + golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 // indirect ) diff --git a/go.sum b/go.sum index 8113aea..8025d04 100644 --- a/go.sum +++ b/go.sum @@ -1,91 +1,94 @@ -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= -github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= -github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.3.0+incompatible h1:ffS62aKWupCWdvcee7nBU9fhnmknOqDPaJAMtfK0ImQ= github.com/docker/docker v28.3.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw= github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o= github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= -github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= -go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= -go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= -golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4= golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= -golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4= golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 h1:3GDAcqdIg1ozBNLgPy4SLT84nfcBjr6rhGtXYtrkWLU= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10/go.mod h1:T97yPqesLiNrOYxkwmhMI0ZIlJDm+p0PMR8eRVeR5tQ= -gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ= gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY= -software.sslmate.com/src/go-pkcs12 v0.5.0 h1:EC6R394xgENTpZ4RltKydeDUjtlM5drOYIG9c6TVj2M= software.sslmate.com/src/go-pkcs12 v0.5.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= From a88d25f36986a476888388f9ec0e4648ed80edb3 Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 3 Jul 2025 09:06:26 -0700 Subject: [PATCH 05/22] Fix missing netstack pack --- go.mod | 7 ++--- go.sum | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index b1dcba5..07a3ce0 100644 --- a/go.mod +++ b/go.mod @@ -12,8 +12,9 @@ require ( golang.org/x/crypto v0.39.0 golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa golang.org/x/net v0.41.0 - golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 - gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 + golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb + golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 + gvisor.dev/gvisor v0.0.0-20250503011706-39ed1f5ac29c software.sslmate.com/src/go-pkcs12 v0.5.0 ) @@ -21,7 +22,6 @@ require ( github.com/Microsoft/go-winio v0.6.0 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect - github.com/containerd/log v0.1.0 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.4.0 // indirect @@ -55,5 +55,4 @@ require ( golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.30.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect - golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 // indirect ) diff --git a/go.sum b/go.sum index 8025d04..2b3bcca 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,47 @@ +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= +github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v28.3.0+incompatible h1:ffS62aKWupCWdvcee7nBU9fhnmknOqDPaJAMtfK0ImQ= github.com/docker/docker v28.3.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -26,33 +52,68 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/ github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= +github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws= +github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= +github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= +go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4= golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -74,21 +135,41 @@ golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= -golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4= -golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA= +golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb h1:whnFRlWMcXI9d+ZbWg+4sHnLp52d5yiIPUxMBSt4X9A= +golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb/go.mod h1:rpwXGsirqLqN2L0JDJQlwOboGHmptD5ZD6T2VmcqhTw= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 h1:3GDAcqdIg1ozBNLgPy4SLT84nfcBjr6rhGtXYtrkWLU= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10/go.mod h1:T97yPqesLiNrOYxkwmhMI0ZIlJDm+p0PMR8eRVeR5tQ= -gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY= +google.golang.org/genproto v0.0.0-20230920204549-e6e6cdab5c13 h1:vlzZttNJGVqTsRFU9AmdnrcO1Znh8Ew9kCD//yjigk0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= +google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= +gvisor.dev/gvisor v0.0.0-20250503011706-39ed1f5ac29c h1:m/r7OM+Y2Ty1sgBQ7Qb27VgIMBW8ZZhT4gLnUyDIhzI= +gvisor.dev/gvisor v0.0.0-20250503011706-39ed1f5ac29c/go.mod h1:3r5CMtNQMKIvBlrmM9xWUNamjKBYPOWyXOjmg5Kts3g= +software.sslmate.com/src/go-pkcs12 v0.5.0 h1:EC6R394xgENTpZ4RltKydeDUjtlM5drOYIG9c6TVj2M= software.sslmate.com/src/go-pkcs12 v0.5.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= From 61a9097bafc9ebf1b8f00d97c503d9b6228ff52a Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 3 Jul 2025 10:09:55 -0700 Subject: [PATCH 06/22] Make linux clients build correctly --- linux.go | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 58 ++++------------------------------------ stub.go | 32 +++++++++++++++++++++++ wg/wg.go | 2 ++ 4 files changed, 119 insertions(+), 53 deletions(-) create mode 100644 linux.go create mode 100644 stub.go diff --git a/linux.go b/linux.go new file mode 100644 index 0000000..076e2f1 --- /dev/null +++ b/linux.go @@ -0,0 +1,80 @@ +//go:build linux + +package main + +import ( + "fmt" + "strings" + + "github.com/fosrl/newt/logger" + "github.com/fosrl/newt/proxy" + "github.com/fosrl/newt/websocket" + "github.com/fosrl/newt/wg" + "github.com/fosrl/newt/wgtester" +) + +var wgService *wg.WireGuardService +var wgTesterServer *wgtester.Server + +func setupClients(client *websocket.Client) { + var host = endpoint + if strings.HasPrefix(host, "http://") { + host = strings.TrimPrefix(host, "http://") + } else if strings.HasPrefix(host, "https://") { + host = strings.TrimPrefix(host, "https://") + } + + host = strings.TrimSuffix(host, "/") + + // Create WireGuard service + wgService, err = wg.NewWireGuardService(interfaceName, mtuInt, generateAndSaveKeyTo, host, id, client) + if err != nil { + logger.Fatal("Failed to create WireGuard service: %v", err) + } + defer wgService.Close(rm) + + wgTesterServer = wgtester.NewServer("0.0.0.0", wgService.Port, id) // TODO: maybe make this the same ip of the wg server? + err := wgTesterServer.Start() + if err != nil { + logger.Error("Failed to start WireGuard tester server: %v", err) + } else { + // Make sure to stop the server on exit + defer wgTesterServer.Stop() + } + + client.OnTokenUpdate(func(token string) { + wgService.SetToken(token) + }) +} + +func closeClients() { + if wgService != nil { + wgService.Close(rm) + wgService = nil + } + + if wgTesterServer != nil { + wgTesterServer.Stop() + wgTesterServer = nil + } +} + +func clientsHandleNewtConnection(publicKey string) { + if wgService != nil { + wgService.SetServerPubKey(publicKey) + } else { + logger.Error("WireGuard service is not initialized, cannot set server public key") + } +} + +func clientsOnConnect() { + if wgService != nil { + wgService.LoadRemoteConfig() + } +} + +func clientsAddProxyTarget(pm *proxy.ProxyManager, tunnelIp string) { + // add a udp proxy for localost and the wgService port + // TODO: make sure this port is not used in a target + pm.AddTarget("udp", tunnelIp, int(wgService.Port), fmt.Sprintf("127.0.0.1:%d", wgService.Port)) +} diff --git a/main.go b/main.go index 0a4fdf3..9b517c7 100644 --- a/main.go +++ b/main.go @@ -19,8 +19,6 @@ import ( "github.com/fosrl/newt/proxy" "github.com/fosrl/newt/updates" "github.com/fosrl/newt/websocket" - "github.com/fosrl/newt/wg" - "github.com/fosrl/newt/wgtester" "golang.zx2c4.com/wireguard/conn" "golang.zx2c4.com/wireguard/device" @@ -255,14 +253,12 @@ func main() { } // Create TUN device and network stack - var wgService *wg.WireGuardService var tun tun.Device var tnet *netstack.Net var dev *device.Device var pm *proxy.ProxyManager var connected bool var wgData WgData - var wgTesterServer *wgtester.Server if acceptClients { // make sure we are running on linux @@ -271,30 +267,7 @@ func main() { os.Exit(1) } - var host = endpoint - if strings.HasPrefix(host, "http://") { - host = strings.TrimPrefix(host, "http://") - } else if strings.HasPrefix(host, "https://") { - host = strings.TrimPrefix(host, "https://") - } - - host = strings.TrimSuffix(host, "/") - - // Create WireGuard service - wgService, err = wg.NewWireGuardService(interfaceName, mtuInt, generateAndSaveKeyTo, host, id, client) - if err != nil { - logger.Fatal("Failed to create WireGuard service: %v", err) - } - defer wgService.Close(rm) - - wgTesterServer = wgtester.NewServer("0.0.0.0", wgService.Port, id) // TODO: maybe make this the same ip of the wg server? - err := wgTesterServer.Start() - if err != nil { - logger.Error("Failed to start WireGuard tester server: %v", err) - } else { - // Make sure to stop the server on exit - defer wgTesterServer.Stop() - } + setupClients(client) } var pingWithRetryStopChan chan struct{} @@ -349,9 +322,7 @@ func main() { return } - if wgService != nil { - wgService.SetServerPubKey(wgData.PublicKey) - } + clientsHandleNewtConnection(wgData.PublicKey) logger.Info("Received: %+v", msg) tun, tnet, err = netstack.CreateNetTUN( @@ -423,12 +394,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub updateTargets(pm, "add", wgData.TunnelIP, "udp", TargetData{Targets: wgData.Targets.UDP}) } - // first make sure the wpgService has a port - if wgService != nil { - // add a udp proxy for localost and the wgService port - // TODO: make sure this port is not used in a target - pm.AddTarget("udp", wgData.TunnelIP, int(wgService.Port), fmt.Sprintf("127.0.0.1:%d", wgService.Port)) - } + clientsAddProxyTarget(pm, wgData.TunnelIP) err = pm.Start() if err != nil { @@ -734,9 +700,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub // request from the server the list of nodes to ping at newt/ping/request stopFunc = client.SendMessageInterval("newt/ping/request", map[string]interface{}{}, 3*time.Second) - if wgService != nil { - wgService.LoadRemoteConfig() - } + clientsOnConnect() } // Send registration message to the server for backward compatibility @@ -755,12 +719,6 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub return nil }) - client.OnTokenUpdate(func(token string) { - if wgService != nil { - wgService.SetToken(token) - } - }) - // Connect to the WebSocket server if err := client.Connect(); err != nil { logger.Fatal("Failed to connect to server: %v", err) @@ -774,13 +732,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub dev.Close() - if wgService != nil { - wgService.Close(rm) - } - - if wgTesterServer != nil { - wgTesterServer.Stop() - } + closeClients() if pm != nil { pm.Stop() diff --git a/stub.go b/stub.go new file mode 100644 index 0000000..e2360ff --- /dev/null +++ b/stub.go @@ -0,0 +1,32 @@ +//go:build !linux + +package main + +import ( + "github.com/fosrl/newt/proxy" + "github.com/fosrl/newt/websocket" +) + +func setupClients(client *websocket.Client) { + return // This function is not implemented for non-Linux systems. +} + +func closeClients() { + // This function is not implemented for non-Linux systems. + return +} + +func clientsHandleNewtConnection(publicKey string) { + // This function is not implemented for non-Linux systems. + return +} + +func clientsOnConnect() { + // This function is not implemented for non-Linux systems. + return +} + +func clientsAddProxyTarget(pm *proxy.ProxyManager, tunnelIp string) { + // This function is not implemented for non-Linux systems. + return +} diff --git a/wg/wg.go b/wg/wg.go index cc86d57..1c378ea 100644 --- a/wg/wg.go +++ b/wg/wg.go @@ -1,3 +1,5 @@ +//go:build linux + package wg import ( From b7d4ea0c84fbd82a1a8c80af7119d6d14db48e48 Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 3 Jul 2025 20:17:21 -0700 Subject: [PATCH 07/22] Fix nil issues --- linux.go | 15 ++++++----- main.go | 6 +++-- websocket/client.go | 64 +++++---------------------------------------- websocket/config.go | 3 --- websocket/types.go | 1 - 5 files changed, 20 insertions(+), 69 deletions(-) diff --git a/linux.go b/linux.go index 076e2f1..790f634 100644 --- a/linux.go +++ b/linux.go @@ -60,20 +60,23 @@ func closeClients() { } func clientsHandleNewtConnection(publicKey string) { - if wgService != nil { - wgService.SetServerPubKey(publicKey) - } else { - logger.Error("WireGuard service is not initialized, cannot set server public key") + if wgService == nil { + return } + wgService.SetServerPubKey(publicKey) } func clientsOnConnect() { - if wgService != nil { - wgService.LoadRemoteConfig() + if wgService == nil { + return } + wgService.LoadRemoteConfig() } func clientsAddProxyTarget(pm *proxy.ProxyManager, tunnelIp string) { + if wgService == nil { + return + } // add a udp proxy for localost and the wgService port // TODO: make sure this port is not used in a target pm.AddTarget("udp", tunnelIp, int(wgService.Port), fmt.Sprintf("127.0.0.1:%d", wgService.Port)) diff --git a/main.go b/main.go index 9b517c7..ed545c5 100644 --- a/main.go +++ b/main.go @@ -547,7 +547,8 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub "pingResults": pingResults, "newtVersion": newtVersion, }, 1*time.Second) - logger.Info("Sent exit node ping results to cloud for selection") + + logger.Debug("Sent exit node ping results to cloud for selection: pingResults=%+v", pingResults) }) client.RegisterHandler("newt/tcp/add", func(msg websocket.WSMessage) { @@ -684,7 +685,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub if err != nil { logger.Error("Failed to send registration message: %v", err) } - logger.Info("Sent registration message") + if err != nil { logger.Error("Failed to send Docker container list: %v", err) } else { @@ -714,6 +715,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub logger.Error("Failed to send registration message: %v", err) return err } + logger.Info("Sent registration message") return nil diff --git a/websocket/client.go b/websocket/client.go index a3538c0..d32698f 100644 --- a/websocket/client.go +++ b/websocket/client.go @@ -126,6 +126,8 @@ func (c *Client) SendMessage(messageType string, data interface{}) error { Data: data, } + logger.Debug("Sending message: %s, data: %+v", messageType, data) + c.writeMux.Lock() defer c.writeMux.Unlock() return c.conn.WriteJSON(msg) @@ -182,62 +184,6 @@ func (c *Client) getToken() (string, error) { } } - // If we already have a token, try to use it - if c.config.Token != "" { - tokenCheckData := map[string]interface{}{ - "newtId": c.config.NewtID, - "secret": c.config.Secret, - "token": c.config.Token, - } - jsonData, err := json.Marshal(tokenCheckData) - if err != nil { - return "", fmt.Errorf("failed to marshal token check data: %w", err) - } - - // Create a new request - req, err := http.NewRequest( - "POST", - baseEndpoint+"/api/v1/auth/newt/get-token", - bytes.NewBuffer(jsonData), - ) - if err != nil { - return "", fmt.Errorf("failed to create request: %w", err) - } - - // Set headers - req.Header.Set("Content-Type", "application/json") - req.Header.Set("X-CSRF-Token", "x-csrf-protection") - - // Make the request - client := &http.Client{} - if tlsConfig != nil { - client.Transport = &http.Transport{ - TLSClientConfig: tlsConfig, - } - } - resp, err := client.Do(req) - if err != nil { - return "", fmt.Errorf("failed to check token validity: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - logger.Error("Token check failed with status code: %d", resp.StatusCode) - return "", fmt.Errorf("token check failed with status code: %d", resp.StatusCode) - } - - var tokenResp TokenResponse - if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil { - logger.Error("Failed to decode token check response.") - return "", fmt.Errorf("failed to decode token check response: %w", err) - } - - // If token is still valid, return it - if tokenResp.Success && tokenResp.Message == "Token session already valid" { - return c.config.Token, nil - } - } - // Get a new token tokenData := map[string]interface{}{ "newtId": c.config.NewtID, @@ -294,6 +240,8 @@ func (c *Client) getToken() (string, error) { return "", fmt.Errorf("received empty token from server") } + logger.Debug("Received token: %s", tokenResp.Data.Token) + return tokenResp.Data.Token, nil } @@ -321,7 +269,9 @@ func (c *Client) establishConnection() error { return fmt.Errorf("failed to get token: %w", err) } - c.onTokenUpdate(token) + if c.onTokenUpdate != nil { + c.onTokenUpdate(token) + } // Parse the base URL to determine protocol and hostname baseURL, err := url.Parse(c.baseURL) diff --git a/websocket/config.go b/websocket/config.go index e2b0055..fe11c5a 100644 --- a/websocket/config.go +++ b/websocket/config.go @@ -48,9 +48,6 @@ func (c *Client) loadConfig() error { if c.config.NewtID == "" { c.config.NewtID = config.NewtID } - if c.config.Token == "" { - c.config.Token = config.Token - } if c.config.Secret == "" { c.config.Secret = config.Secret } diff --git a/websocket/types.go b/websocket/types.go index 0ea24fc..54d33f1 100644 --- a/websocket/types.go +++ b/websocket/types.go @@ -3,7 +3,6 @@ package websocket type Config struct { NewtID string `json:"newtId"` Secret string `json:"secret"` - Token string `json:"token"` Endpoint string `json:"endpoint"` TlsClientCert string `json:"tlsClientCert"` } From 07bd283604ac9af096a14484ea7e65bdf8167899 Mon Sep 17 00:00:00 2001 From: Owen Date: Sat, 5 Jul 2025 18:14:33 -0700 Subject: [PATCH 08/22] Remove dup code --- main.go | 95 +++++++++++++++++++++++++++------------------------------ 1 file changed, 45 insertions(+), 50 deletions(-) diff --git a/main.go b/main.go index ed545c5..ca86508 100644 --- a/main.go +++ b/main.go @@ -272,6 +272,35 @@ func main() { var pingWithRetryStopChan chan struct{} + closeWgTunnel := func() { + if pingStopChan != nil { + // Stop the ping check + close(pingStopChan) + pingStopChan = nil + } + + // Stop proxy manager if running + if pm != nil { + pm.Stop() + pm = nil + } + + // Close WireGuard device first - this will automatically close the TUN device + if dev != nil { + dev.Close() + dev = nil + } + + // Clear references but don't manually close since dev.Close() already did it + if tnet != nil { + tnet = nil + } + if tun != nil { + tun = nil // Don't call tun.Close() here since dev.Close() already closed it + } + + } + // Register handlers for different message types client.RegisterHandler("newt/wg/connect", func(msg websocket.WSMessage) { logger.Info("Received registration message") @@ -281,33 +310,10 @@ func main() { } if connected { - if pingStopChan != nil { - // Stop the ping check - close(pingStopChan) - pingStopChan = nil - } - - // Stop proxy manager if running - if pm != nil { - pm.Stop() - pm = nil - } - - // Close WireGuard device first - this will automatically close the TUN device - if dev != nil { - dev.Close() - dev = nil - } + // Mark as disconnected - // Clear references but don't manually close since dev.Close() already did it - if tnet != nil { - tnet = nil - } - if tun != nil { - tun = nil // Don't call tun.Close() here since dev.Close() already closed it - } + closeWgTunnel() - // Mark as disconnected connected = false } @@ -405,31 +411,8 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub client.RegisterHandler("newt/wg/reconnect", func(msg websocket.WSMessage) { logger.Info("Received reconnect message") - if pingStopChan != nil { - // Stop the ping check - close(pingStopChan) - pingStopChan = nil - } - - // Stop proxy manager if running - if pm != nil { - pm.Stop() - pm = nil - } - - // Close WireGuard device first - this will automatically close the TUN device - if dev != nil { - dev.Close() - dev = nil - } - - // Clear references but don't manually close since dev.Close() already did it - if tnet != nil { - tnet = nil - } - if tun != nil { - tun = nil // Don't call tun.Close() here since dev.Close() already closed it - } + // Close the WireGuard device and TUN + closeWgTunnel() // Mark as disconnected connected = false @@ -446,6 +429,18 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub logger.Info("Tunnel destroyed, ready for reconnection") }) + client.RegisterHandler("newt/wg/terminate", func(msg websocket.WSMessage) { + logger.Info("Received termination message") + + // Close the WireGuard device and TUN + closeWgTunnel() + + // Mark as disconnected + connected = false + + logger.Info("Tunnel destroyed, ready for reconnection") + }) + client.RegisterHandler("newt/ping/exitNodes", func(msg websocket.WSMessage) { logger.Info("Received ping message") if stopFunc != nil { From e4bdbbec7c58916561f64da19fdce79d0144d136 Mon Sep 17 00:00:00 2001 From: Owen Date: Tue, 8 Jul 2025 08:48:27 -0700 Subject: [PATCH 09/22] Adjust logging --- main.go | 24 ++++++++++++++++-------- proxy/manager.go | 3 ++- util.go | 10 +++++----- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/main.go b/main.go index ca86508..613ca23 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "encoding/json" "flag" "fmt" + "net" "net/http" "net/netip" "os" @@ -86,8 +87,8 @@ var ( dockerSocket string dockerEnforceNetworkValidation string dockerEnforceNetworkValidationBool bool - pingInterval = 1 * time.Second - pingTimeout = 2 * time.Second + pingInterval = 2 * time.Second + pingTimeout = 3 * time.Second publicKey wgtypes.Key pingStopChan chan struct{} stopFunc func() @@ -330,7 +331,7 @@ func main() { clientsHandleNewtConnection(wgData.PublicKey) - logger.Info("Received: %+v", msg) + logger.Debug("Received: %+v", msg) tun, tnet, err = netstack.CreateNetTUN( []netip.Addr{netip.MustParseAddr(wgData.TunnelIP)}, []netip.Addr{netip.MustParseAddr(dns)}, @@ -345,6 +346,14 @@ func main() { "wireguard: ", )) + host, _, err := net.SplitHostPort(wgData.Endpoint) + if err != nil { + logger.Error("Failed to split endpoint: %v", err) + return + } + + logger.Info("Connecting to endpoint: %s", host) + endpoint, err := resolveDomain(wgData.Endpoint) if err != nil { logger.Error("Failed to resolve endpoint: %v", err) @@ -369,7 +378,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub logger.Error("Failed to bring up WireGuard device: %v", err) } - logger.Info("WireGuard device created. Lets ping the server now...") + logger.Debug("WireGuard device created. Lets ping the server now...") // Even if pingWithRetry returns an error, it will continue trying in the background if pingWithRetryStopChan != nil { @@ -382,7 +391,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub // Always mark as connected and start the proxy manager regardless of initial ping result // as the pings will continue in the background if !connected { - logger.Info("Starting ping check") + logger.Debug("Starting ping check") pingStopChan = startPingCheck(tnet, wgData.ServerIP, client) } @@ -417,7 +426,6 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub // Mark as disconnected connected = false - // start asking for the exit nodes again if stopFunc != nil { stopFunc() // stop the ws from sending more requests stopFunc = nil // reset stopFunc to nil to avoid double stopping @@ -438,7 +446,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub // Mark as disconnected connected = false - logger.Info("Tunnel destroyed, ready for reconnection") + logger.Info("Tunnel destroyed") }) client.RegisterHandler("newt/ping/exitNodes", func(msg websocket.WSMessage) { @@ -547,7 +555,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub }) client.RegisterHandler("newt/tcp/add", func(msg websocket.WSMessage) { - logger.Info("Received: %+v", msg) + logger.Debug("Received: %+v", msg) // if there is no wgData or pm, we can't add targets if wgData.TunnelIP == "" || pm == nil { diff --git a/proxy/manager.go b/proxy/manager.go index 0792acb..35d023a 100644 --- a/proxy/manager.go +++ b/proxy/manager.go @@ -213,7 +213,8 @@ func (pm *ProxyManager) startTarget(proto, listenIP string, port int, targetAddr return fmt.Errorf("unsupported protocol: %s", proto) } - logger.Info("Started %s proxy from %s:%d to %s", proto, listenIP, port, targetAddr) + logger.Info("Started %s proxy to %s", proto, targetAddr) + logger.Debug("Started %s proxy from %s:%d to %s", proto, listenIP, port, targetAddr) return nil } diff --git a/util.go b/util.go index c0f634c..9bdab59 100644 --- a/util.go +++ b/util.go @@ -112,10 +112,10 @@ func pingWithRetry(tnet *netstack.Net, dst string, timeout time.Duration) (stopC retryDelay := initialRetryDelay // First try with the initial parameters - logger.Info("Ping attempt %d", attempt) + logger.Debug("Ping attempt %d", attempt) if latency, err := ping(tnet, dst, timeout); err == nil { // Successful ping - logger.Info("Ping latency: %v", latency) + logger.Debug("Ping latency: %v", latency) logger.Info("Tunnel connection to server established successfully!") if healthFile != "" { err := os.WriteFile(healthFile, []byte("ok"), 0644) @@ -137,7 +137,7 @@ func pingWithRetry(tnet *netstack.Net, dst string, timeout time.Duration) (stopC case <-stopChan: return default: - logger.Info("Ping attempt %d", attempt) + logger.Debug("Ping attempt %d", attempt) if latency, err := ping(tnet, dst, timeout); err != nil { logger.Warn("Ping attempt %d failed: %v", attempt, err) @@ -155,8 +155,8 @@ func pingWithRetry(tnet *netstack.Net, dst string, timeout time.Duration) (stopC attempt++ } else { // Successful ping - logger.Info("Ping succeeded after %d attempts", attempt) - logger.Info("Ping latency: %v", latency) + logger.Debug("Ping succeeded after %d attempts", attempt) + logger.Debug("Ping latency: %v", latency) logger.Info("Tunnel connection to server established successfully!") if healthFile != "" { err := os.WriteFile(healthFile, []byte("ok"), 0644) From 221d5862fb72ca30b6ebbf06530477d4dcd9f520 Mon Sep 17 00:00:00 2001 From: Owen Date: Tue, 8 Jul 2025 08:48:39 -0700 Subject: [PATCH 10/22] Fix disconnect errors about closed connection --- websocket/client.go | 72 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/websocket/client.go b/websocket/client.go index d32698f..98f07e6 100644 --- a/websocket/client.go +++ b/websocket/client.go @@ -102,16 +102,31 @@ func (c *Client) Connect() error { return nil } -// Close closes the WebSocket connection +// Close closes the WebSocket connection gracefully func (c *Client) Close() error { - close(c.done) - if c.conn != nil { - return c.conn.Close() + // Signal shutdown to all goroutines first + select { + case <-c.done: + // Already closed + return nil + default: + close(c.done) } - // stop the ping monitor + // Set connection status to false c.setConnected(false) + // Close the WebSocket connection gracefully + if c.conn != nil { + // Send close message + c.writeMux.Lock() + c.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) + c.writeMux.Unlock() + + // Close the connection + return c.conn.Close() + } + return nil } @@ -351,9 +366,16 @@ func (c *Client) pingMonitor() { err := c.conn.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(c.pingTimeout)) c.writeMux.Unlock() if err != nil { - logger.Error("Ping failed: %v", err) - c.reconnect() - return + // Check if we're shutting down before logging error and reconnecting + select { + case <-c.done: + // Expected during shutdown + return + default: + logger.Error("Ping failed: %v", err) + c.reconnect() + return + } } } } @@ -365,7 +387,14 @@ func (c *Client) readPumpWithDisconnectDetection() { if c.conn != nil { c.conn.Close() } - c.reconnect() + // Only attempt reconnect if we're not shutting down + select { + case <-c.done: + // Shutting down, don't reconnect + return + default: + c.reconnect() + } }() for { @@ -376,8 +405,21 @@ func (c *Client) readPumpWithDisconnectDetection() { var msg WSMessage err := c.conn.ReadJSON(&msg) if err != nil { - logger.Error("WebSocket read error: %v", err) - return // triggers reconnect via defer + // Check if we're shutting down before logging error + select { + case <-c.done: + // Expected during shutdown, don't log as error + logger.Debug("WebSocket connection closed during shutdown") + return + default: + // Unexpected error during normal operation + if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure, websocket.CloseNormalClosure) { + logger.Error("WebSocket read error: %v", err) + } else { + logger.Debug("WebSocket connection closed: %v", err) + } + return // triggers reconnect via defer + } } c.handlersMux.RLock() @@ -396,7 +438,13 @@ func (c *Client) reconnect() { c.conn = nil } - go c.connectWithRetry() + // Only reconnect if we're not shutting down + select { + case <-c.done: + return + default: + go c.connectWithRetry() + } } func (c *Client) setConnected(status bool) { From 53397663ef02003927574fc8b1cef8d7c809eb83 Mon Sep 17 00:00:00 2001 From: Owen Date: Tue, 8 Jul 2025 17:18:43 -0700 Subject: [PATCH 11/22] Adjust logging --- main.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 613ca23..8af6403 100644 --- a/main.go +++ b/main.go @@ -699,11 +699,12 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub client.OnConnect(func() error { publicKey = privateKey.PublicKey() logger.Debug("Public key: %s", publicKey) + logger.Info("Websocket connected") if !connected { // request from the server the list of nodes to ping at newt/ping/request stopFunc = client.SendMessageInterval("newt/ping/request", map[string]interface{}{}, 3*time.Second) - + logger.Info("Requesting exit nodes from server") clientsOnConnect() } @@ -719,8 +720,6 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub return err } - logger.Info("Sent registration message") - return nil }) From 9410b92169fd1f03d0804109f400811cf5a223df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 09:23:04 +0000 Subject: [PATCH 12/22] Bump golang in the patch-updates group Bumps the patch-updates group with 1 update: golang. Updates `golang` from 1.24.4-alpine to 1.24.5-alpine --- updated-dependencies: - dependency-name: golang dependency-version: 1.24.5-alpine dependency-type: direct:production update-type: version-update:semver-patch dependency-group: patch-updates ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b25ebe3..c54568a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.24.4-alpine AS builder +FROM golang:1.24.5-alpine AS builder # Set the working directory inside the container WORKDIR /app From 99506a10f6cb4637512ec4d8dc8b1bb0d89a7dba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Jul 2025 10:01:34 +0000 Subject: [PATCH 13/22] Bump github.com/docker/docker in the prod-patch-updates group Bumps the prod-patch-updates group with 1 update: [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/docker` from 28.3.1+incompatible to 28.3.2+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v28.3.1...v28.3.2) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-version: 28.3.2+incompatible dependency-type: direct:production update-type: version-update:semver-patch dependency-group: prod-patch-updates ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b6c3839..234f09e 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.1 toolchain go1.23.2 require ( - github.com/docker/docker v28.3.1+incompatible + github.com/docker/docker v28.3.2+incompatible github.com/gorilla/websocket v1.5.3 golang.org/x/net v0.41.0 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 diff --git a/go.sum b/go.sum index e074360..8509295 100644 --- a/go.sum +++ b/go.sum @@ -15,8 +15,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.3.1+incompatible h1:20+BmuA9FXlCX4ByQ0vYJcUEnOmRM6XljDnFWR+jCyY= -github.com/docker/docker v28.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.3.2+incompatible h1:wn66NJ6pWB1vBZIilP8G3qQPqHy5XymfYn5vsqeA5oA= +github.com/docker/docker v28.3.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= From 2d9b761de98c56392a7d5dc98b95817f896ed0a6 Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 10 Jul 2025 17:17:12 -0700 Subject: [PATCH 14/22] Get newt script --- get-newt.sh | 235 ++++++++++++++++++++++++++++++++++++++++++++++++++++ util.go | 6 +- 2 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 get-newt.sh diff --git a/get-newt.sh b/get-newt.sh new file mode 100644 index 0000000..af4c248 --- /dev/null +++ b/get-newt.sh @@ -0,0 +1,235 @@ +#!/bin/bash + +# Get Newt - Cross-platform installation script +# Usage: curl -fsSL https://raw.githubusercontent.com/your-repo/get-newt.sh | bash + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# GitHub repository info +REPO="fosrl/newt" +GITHUB_API_URL="https://api.github.com/repos/${REPO}/releases/latest" + +# Function to print colored output +print_status() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Function to get latest version from GitHub API +get_latest_version() { + local latest_info + + if command -v curl >/dev/null 2>&1; then + latest_info=$(curl -fsSL "$GITHUB_API_URL" 2>/dev/null) + elif command -v wget >/dev/null 2>&1; then + latest_info=$(wget -qO- "$GITHUB_API_URL" 2>/dev/null) + else + print_error "Neither curl nor wget is available. Please install one of them." >&2 + exit 1 + fi + + if [ -z "$latest_info" ]; then + print_error "Failed to fetch latest version information" >&2 + exit 1 + fi + + # Extract version from JSON response (works without jq) + local version=$(echo "$latest_info" | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/') + + if [ -z "$version" ]; then + print_error "Could not parse version from GitHub API response" >&2 + exit 1 + fi + + # Remove 'v' prefix if present + version=$(echo "$version" | sed 's/^v//') + + echo "$version" +} + +# Detect OS and architecture +detect_platform() { + local os arch + + # Detect OS + case "$(uname -s)" in + Linux*) os="linux" ;; + Darwin*) os="darwin" ;; + MINGW*|MSYS*|CYGWIN*) os="windows" ;; + FreeBSD*) os="freebsd" ;; + *) + print_error "Unsupported operating system: $(uname -s)" + exit 1 + ;; + esac + + # Detect architecture + case "$(uname -m)" in + x86_64|amd64) arch="amd64" ;; + arm64|aarch64) arch="arm64" ;; + armv7l|armv6l) + if [ "$os" = "linux" ]; then + if [ "$(uname -m)" = "armv6l" ]; then + arch="arm32v6" + else + arch="arm32" + fi + else + arch="arm64" # Default for non-Linux ARM + fi + ;; + riscv64) + if [ "$os" = "linux" ]; then + arch="riscv64" + else + print_error "RISC-V architecture only supported on Linux" + exit 1 + fi + ;; + *) + print_error "Unsupported architecture: $(uname -m)" + exit 1 + ;; + esac + + echo "${os}_${arch}" +} + +# Get installation directory +get_install_dir() { + if [ "$OS" = "windows" ]; then + echo "$HOME/bin" + else + # Try to use a directory in PATH, fallback to ~/.local/bin + if echo "$PATH" | grep -q "/usr/local/bin"; then + if [ -w "/usr/local/bin" ] 2>/dev/null; then + echo "/usr/local/bin" + else + echo "$HOME/.local/bin" + fi + else + echo "$HOME/.local/bin" + fi + fi +} + +# Download and install newt +install_newt() { + local platform="$1" + local install_dir="$2" + local binary_name="newt_${platform}" + local exe_suffix="" + + # Add .exe suffix for Windows + if [[ "$platform" == *"windows"* ]]; then + binary_name="${binary_name}.exe" + exe_suffix=".exe" + fi + + local download_url="${BASE_URL}/${binary_name}" + local temp_file="/tmp/newt${exe_suffix}" + local final_path="${install_dir}/newt${exe_suffix}" + + print_status "Downloading newt from ${download_url}" + + # Download the binary + if command -v curl >/dev/null 2>&1; then + curl -fsSL "$download_url" -o "$temp_file" + elif command -v wget >/dev/null 2>&1; then + wget -q "$download_url" -O "$temp_file" + else + print_error "Neither curl nor wget is available. Please install one of them." + exit 1 + fi + + # Create install directory if it doesn't exist + mkdir -p "$install_dir" + + # Move binary to install directory + mv "$temp_file" "$final_path" + + # Make executable (not needed on Windows, but doesn't hurt) + chmod +x "$final_path" + + print_status "newt installed to ${final_path}" + + # Check if install directory is in PATH + if ! echo "$PATH" | grep -q "$install_dir"; then + print_warning "Install directory ${install_dir} is not in your PATH." + print_warning "Add it to your PATH by adding this line to your shell profile:" + print_warning " export PATH=\"${install_dir}:\$PATH\"" + fi +} + +# Verify installation +verify_installation() { + local install_dir="$1" + local exe_suffix="" + + if [[ "$PLATFORM" == *"windows"* ]]; then + exe_suffix=".exe" + fi + + local newt_path="${install_dir}/newt${exe_suffix}" + + if [ -f "$newt_path" ] && [ -x "$newt_path" ]; then + print_status "Installation successful!" + print_status "newt version: $("$newt_path" --version 2>/dev/null || echo "unknown")" + return 0 + else + print_error "Installation failed. Binary not found or not executable." + return 1 + fi +} + +# Main installation process +main() { + print_status "Installing latest version of newt..." + + # Get latest version + print_status "Fetching latest version from GitHub..." + VERSION=$(get_latest_version) + print_status "Latest version: v${VERSION}" + + # Set base URL with the fetched version + BASE_URL="https://github.com/${REPO}/releases/download/${VERSION}" + + # Detect platform + PLATFORM=$(detect_platform) + print_status "Detected platform: ${PLATFORM}" + + # Get install directory + INSTALL_DIR=$(get_install_dir) + print_status "Install directory: ${INSTALL_DIR}" + + # Install newt + install_newt "$PLATFORM" "$INSTALL_DIR" + + # Verify installation + if verify_installation "$INSTALL_DIR"; then + print_status "newt is ready to use!" + if [[ "$PLATFORM" == *"windows"* ]]; then + print_status "Run 'newt --help' to get started" + else + print_status "Run 'newt --help' to get started" + fi + else + exit 1 + fi +} + +# Run main function +main "$@" \ No newline at end of file diff --git a/util.go b/util.go index 9bdab59..967f12e 100644 --- a/util.go +++ b/util.go @@ -192,7 +192,11 @@ func startPingCheck(tnet *netstack.Net, serverIP string, client *websocket.Clien _, err := ping(tnet, serverIP, pingTimeout) if err != nil { consecutiveFailures++ - logger.Warn("Periodic ping failed (%d consecutive failures): %v", consecutiveFailures, err) + if consecutiveFailures == 1 { + logger.Debug("Periodic ping failed (%d consecutive failures): %v", consecutiveFailures, err) + } else { + logger.Warn("Periodic ping failed (%d consecutive failures): %v", consecutiveFailures, err) + } if consecutiveFailures >= 3 && currentInterval < maxInterval { if !connectionLost { connectionLost = true From b1cfd3ba026c0561813194956b5c16c6dd0ca374 Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 10 Jul 2025 17:23:26 -0700 Subject: [PATCH 15/22] Update link --- get-newt.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/get-newt.sh b/get-newt.sh index af4c248..5541707 100644 --- a/get-newt.sh +++ b/get-newt.sh @@ -1,7 +1,7 @@ #!/bin/bash # Get Newt - Cross-platform installation script -# Usage: curl -fsSL https://raw.githubusercontent.com/your-repo/get-newt.sh | bash +# Usage: curl -fsSL https://raw.githubusercontent.com/fosrl/newt/get-newt.sh | bash set -e From 9eb8e5122a6aeae3af7f1634181f17203495f7c3 Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 10 Jul 2025 17:26:58 -0700 Subject: [PATCH 16/22] Fix link again --- get-newt.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/get-newt.sh b/get-newt.sh index 5541707..d57f69a 100644 --- a/get-newt.sh +++ b/get-newt.sh @@ -1,7 +1,7 @@ #!/bin/bash # Get Newt - Cross-platform installation script -# Usage: curl -fsSL https://raw.githubusercontent.com/fosrl/newt/get-newt.sh | bash +# Usage: curl -fsSL https://raw.githubusercontent.com/fosrl/newt/refs/heads/main/get-newt.sh | bash set -e From 4d343e3541064ecbf838c8959246280796091a10 Mon Sep 17 00:00:00 2001 From: Wouter van Elten Date: Fri, 11 Jul 2025 08:14:32 +0200 Subject: [PATCH 17/22] Update README.md for health check Added explanation of health_file --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d88096..997745e 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ When Newt receives WireGuard control messages, it will use the information encod - `tls-client-cert` (optional): Client certificate (p12 or pfx) for mTLS. See [mTLS](#mtls) - `docker-socket` (optional): Set the Docker socket to use the container discovery integration - `docker-enforce-network-validation` (optional): Validate the container target is on the same network as the newt process +- `health_file` (optional): Check if connection to WG server (pangolin) is ok. creates a file if ok, removes it if not ok. Can be used with docker healtcheck to restart newt - Example: @@ -61,7 +62,8 @@ services: environment: - PANGOLIN_ENDPOINT=https://example.com - NEWT_ID=2ix2t8xk22ubpfy - - NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2 + - NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2 + - HEALTH_FILE=/tmp/healthy ``` You can also pass the CLI args to the container: @@ -76,6 +78,7 @@ services: - --id 31frd0uzbjvp721 - --secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6 - --endpoint https://example.com + - --health_file /tmp/healthy ``` ### Docker Socket Integration From 6160e4c8a6fbed46a9a948b8470d3a9462ddf500 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 09:32:02 +0000 Subject: [PATCH 18/22] Bump the prod-minor-updates group with 2 updates Bumps the prod-minor-updates group with 2 updates: [golang.org/x/crypto](https://github.com/golang/crypto) and [golang.org/x/net](https://github.com/golang/net). Updates `golang.org/x/crypto` from 0.39.0 to 0.40.0 - [Commits](https://github.com/golang/crypto/compare/v0.39.0...v0.40.0) Updates `golang.org/x/net` from 0.41.0 to 0.42.0 - [Commits](https://github.com/golang/net/compare/v0.41.0...v0.42.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.40.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-minor-updates - dependency-name: golang.org/x/net dependency-version: 0.42.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 | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index efbf944..e336958 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,9 @@ require ( github.com/google/gopacket v1.1.19 github.com/gorilla/websocket v1.5.3 github.com/vishvananda/netlink v1.3.0 - golang.org/x/crypto v0.39.0 + golang.org/x/crypto v0.40.0 golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa - golang.org/x/net v0.41.0 + golang.org/x/net v0.42.0 golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 gvisor.dev/gvisor v0.0.0-20250503011706-39ed1f5ac29c @@ -51,7 +51,7 @@ require ( go.opentelemetry.io/otel/trace v1.36.0 // indirect golang.org/x/mod v0.23.0 // indirect golang.org/x/sync v0.11.0 // indirect - golang.org/x/sys v0.33.0 // indirect + golang.org/x/sys v0.34.0 // indirect golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.30.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect diff --git a/go.sum b/go.sum index c0e7b45..a190a1b 100644 --- a/go.sum +++ b/go.sum @@ -105,8 +105,8 @@ go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAj golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4= golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= @@ -119,8 +119,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -131,12 +131,12 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From b881808caeac1df805b8c3072c726d7cfde98423 Mon Sep 17 00:00:00 2001 From: Owen Date: Fri, 11 Jul 2025 16:35:39 -0700 Subject: [PATCH 19/22] Loosen up the ping intervals --- main.go | 12 ++++++------ util.go | 15 +++++++-------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/main.go b/main.go index 8af6403..bcc1da9 100644 --- a/main.go +++ b/main.go @@ -87,8 +87,8 @@ var ( dockerSocket string dockerEnforceNetworkValidation string dockerEnforceNetworkValidationBool bool - pingInterval = 2 * time.Second - pingTimeout = 3 * time.Second + pingInterval time.Duration + pingTimeout time.Duration publicKey wgtypes.Key pingStopChan chan struct{} stopFunc func() @@ -151,17 +151,17 @@ func main() { flag.StringVar(&dockerSocket, "docker-socket", "", "Path to Docker socket (typically /var/run/docker.sock)") } if pingIntervalStr == "" { - flag.StringVar(&pingIntervalStr, "ping-interval", "1s", "Interval for pinging the server (default 1s)") + flag.StringVar(&pingIntervalStr, "ping-interval", "3s", "Interval for pinging the server (default 3s)") } if pingTimeoutStr == "" { - flag.StringVar(&pingTimeoutStr, "ping-timeout", "2s", " Timeout for each ping (default 2s)") + flag.StringVar(&pingTimeoutStr, "ping-timeout", "3s", " Timeout for each ping (default 3s)") } if pingIntervalStr != "" { pingInterval, err = time.ParseDuration(pingIntervalStr) if err != nil { fmt.Printf("Invalid PING_INTERVAL value: %s, using default 1 second\n", pingIntervalStr) - pingInterval = 1 * time.Second + pingInterval = 3 * time.Second } } @@ -169,7 +169,7 @@ func main() { pingTimeout, err = time.ParseDuration(pingTimeoutStr) if err != nil { fmt.Printf("Invalid PING_TIMEOUT value: %s, using default 2 seconds\n", pingTimeoutStr) - pingTimeout = 2 * time.Second + pingTimeout = 3 * time.Second } } diff --git a/util.go b/util.go index 967f12e..068a9f7 100644 --- a/util.go +++ b/util.go @@ -175,9 +175,8 @@ func pingWithRetry(tnet *netstack.Net, dst string, timeout time.Duration) (stopC } func startPingCheck(tnet *netstack.Net, serverIP string, client *websocket.Client) chan struct{} { - initialInterval := pingInterval - maxInterval := 3 * time.Second - currentInterval := initialInterval + maxInterval := 6 * time.Second + currentInterval := pingInterval consecutiveFailures := 0 connectionLost := false @@ -192,12 +191,12 @@ func startPingCheck(tnet *netstack.Net, serverIP string, client *websocket.Clien _, err := ping(tnet, serverIP, pingTimeout) if err != nil { consecutiveFailures++ - if consecutiveFailures == 1 { + if consecutiveFailures < 4 { logger.Debug("Periodic ping failed (%d consecutive failures): %v", consecutiveFailures, err) } else { logger.Warn("Periodic ping failed (%d consecutive failures): %v", consecutiveFailures, err) } - if consecutiveFailures >= 3 && currentInterval < maxInterval { + if consecutiveFailures >= 8 && currentInterval < maxInterval { if !connectionLost { connectionLost = true logger.Warn("Connection to server lost. Continuous reconnection attempts will be made.") @@ -235,10 +234,10 @@ func startPingCheck(tnet *netstack.Net, serverIP string, client *websocket.Clien } } } - if currentInterval > initialInterval { + if currentInterval > pingInterval { currentInterval = time.Duration(float64(currentInterval) * 0.8) - if currentInterval < initialInterval { - currentInterval = initialInterval + if currentInterval < pingInterval { + currentInterval = pingInterval } ticker.Reset(currentInterval) logger.Info("Decreased ping check interval to %v after successful ping", currentInterval) From ce4f3e4cdff02685d72277fd6e39b6f749d36a30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Jul 2025 23:07:14 +0000 Subject: [PATCH 20/22] Bump github.com/vishvananda/netlink in the prod-patch-updates group Bumps the prod-patch-updates group with 1 update: [github.com/vishvananda/netlink](https://github.com/vishvananda/netlink). Updates `github.com/vishvananda/netlink` from 1.3.0 to 1.3.1 - [Release notes](https://github.com/vishvananda/netlink/releases) - [Commits](https://github.com/vishvananda/netlink/compare/v1.3.0...v1.3.1) --- updated-dependencies: - dependency-name: github.com/vishvananda/netlink dependency-version: 1.3.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: prod-patch-updates ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index e336958..739d4fd 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/docker/docker v28.3.2+incompatible github.com/google/gopacket v1.1.19 github.com/gorilla/websocket v1.5.3 - github.com/vishvananda/netlink v1.3.0 + github.com/vishvananda/netlink v1.3.1 golang.org/x/crypto v0.40.0 golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa golang.org/x/net v0.42.0 @@ -42,7 +42,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/vishvananda/netns v0.0.4 // indirect + github.com/vishvananda/netns v0.0.5 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect go.opentelemetry.io/otel v1.36.0 // indirect diff --git a/go.sum b/go.sum index a190a1b..33ff3b1 100644 --- a/go.sum +++ b/go.sum @@ -76,10 +76,10 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= -github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= -github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= -github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= +github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= +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= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= From f513f97fc39163bf3c35137e306ad52750a01dc7 Mon Sep 17 00:00:00 2001 From: Owen Date: Sun, 13 Jul 2025 16:07:46 -0700 Subject: [PATCH 21/22] Working on better ping --- main.go | 21 ++++++++-- util.go | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 126 insertions(+), 15 deletions(-) diff --git a/main.go b/main.go index bcc1da9..b84ae8b 100644 --- a/main.go +++ b/main.go @@ -154,23 +154,27 @@ func main() { flag.StringVar(&pingIntervalStr, "ping-interval", "3s", "Interval for pinging the server (default 3s)") } if pingTimeoutStr == "" { - flag.StringVar(&pingTimeoutStr, "ping-timeout", "3s", " Timeout for each ping (default 3s)") + flag.StringVar(&pingTimeoutStr, "ping-timeout", "5s", " Timeout for each ping (default 3s)") } if pingIntervalStr != "" { pingInterval, err = time.ParseDuration(pingIntervalStr) if err != nil { - fmt.Printf("Invalid PING_INTERVAL value: %s, using default 1 second\n", pingIntervalStr) + fmt.Printf("Invalid PING_INTERVAL value: %s, using default 3 seconds\n", pingIntervalStr) pingInterval = 3 * time.Second } + } else { + pingInterval = 3 * time.Second } if pingTimeoutStr != "" { pingTimeout, err = time.ParseDuration(pingTimeoutStr) if err != nil { - fmt.Printf("Invalid PING_TIMEOUT value: %s, using default 2 seconds\n", pingTimeoutStr) - pingTimeout = 3 * time.Second + fmt.Printf("Invalid PING_TIMEOUT value: %s, using default 5 seconds\n", pingTimeoutStr) + pingTimeout = 5 * time.Second } + } else { + pingTimeout = 5 * time.Second } if dockerEnforceNetworkValidation == "" { @@ -386,6 +390,15 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub close(pingWithRetryStopChan) pingWithRetryStopChan = nil } + // Use reliable ping for initial connection test + logger.Debug("Testing initial connection with reliable ping...") + _, err = reliablePing(tnet, wgData.ServerIP, pingTimeout, 5) + if err != nil { + logger.Warn("Initial reliable ping failed, but continuing: %v", err) + } else { + logger.Info("Initial connection test successful!") + } + pingWithRetryStopChan, _ = pingWithRetry(tnet, wgData.ServerIP, pingTimeout) // Always mark as connected and start the proxy manager regardless of initial ping result diff --git a/util.go b/util.go index 068a9f7..7d6da4f 100644 --- a/util.go +++ b/util.go @@ -45,9 +45,17 @@ func ping(tnet *netstack.Net, dst string, timeout time.Duration) (time.Duration, } defer socket.Close() + // Set socket buffer sizes to handle high bandwidth scenarios + if tcpConn, ok := socket.(interface{ SetReadBuffer(int) error }); ok { + tcpConn.SetReadBuffer(64 * 1024) + } + if tcpConn, ok := socket.(interface{ SetWriteBuffer(int) error }); ok { + tcpConn.SetWriteBuffer(64 * 1024) + } + requestPing := icmp.Echo{ Seq: rand.Intn(1 << 16), - Data: []byte("f"), + Data: []byte("newtping"), } icmpBytes, err := (&icmp.Message{Type: ipv4.ICMPTypeEcho, Code: 0, Body: &requestPing}).Marshal(nil) @@ -65,12 +73,14 @@ func ping(tnet *netstack.Net, dst string, timeout time.Duration) (time.Duration, return 0, fmt.Errorf("failed to write ICMP packet: %w", err) } - n, err := socket.Read(icmpBytes[:]) + // Use larger buffer for reading to handle potential network congestion + readBuffer := make([]byte, 1500) + n, err := socket.Read(readBuffer) if err != nil { return 0, fmt.Errorf("failed to read ICMP packet: %w", err) } - replyPacket, err := icmp.ParseMessage(1, icmpBytes[:n]) + replyPacket, err := icmp.ParseMessage(1, readBuffer[:n]) if err != nil { return 0, fmt.Errorf("failed to parse ICMP packet: %w", err) } @@ -92,6 +102,51 @@ func ping(tnet *netstack.Net, dst string, timeout time.Duration) (time.Duration, return latency, nil } +// reliablePing performs multiple ping attempts with adaptive timeout +func reliablePing(tnet *netstack.Net, dst string, baseTimeout time.Duration, maxAttempts int) (time.Duration, error) { + var lastErr error + var totalLatency time.Duration + successCount := 0 + + for attempt := 1; attempt <= maxAttempts; attempt++ { + // Adaptive timeout: increase timeout for later attempts + timeout := baseTimeout + time.Duration(attempt-1)*500*time.Millisecond + + // Add jitter to prevent thundering herd + jitter := time.Duration(rand.Intn(100)) * time.Millisecond + timeout += jitter + + latency, err := ping(tnet, dst, timeout) + if err != nil { + lastErr = err + logger.Debug("Ping attempt %d/%d failed: %v", attempt, maxAttempts, err) + + // Brief pause between attempts with exponential backoff + if attempt < maxAttempts { + backoff := time.Duration(attempt) * 50 * time.Millisecond + time.Sleep(backoff) + } + continue + } + + totalLatency += latency + successCount++ + + // If we get at least one success, we can return early for health checks + if successCount > 0 { + avgLatency := totalLatency / time.Duration(successCount) + logger.Debug("Reliable ping succeeded after %d attempts, avg latency: %v", attempt, avgLatency) + return avgLatency, nil + } + } + + if successCount == 0 { + return 0, fmt.Errorf("all %d ping attempts failed, last error: %v", maxAttempts, lastErr) + } + + return totalLatency / time.Duration(successCount), nil +} + func pingWithRetry(tnet *netstack.Net, dst string, timeout time.Duration) (stopChan chan struct{}, err error) { if healthFile != "" { @@ -180,6 +235,9 @@ func startPingCheck(tnet *netstack.Net, serverIP string, client *websocket.Clien consecutiveFailures := 0 connectionLost := false + // Track recent latencies for adaptive timeout calculation + recentLatencies := make([]time.Duration, 0, 10) + pingStopChan := make(chan struct{}) go func() { @@ -188,18 +246,52 @@ func startPingCheck(tnet *netstack.Net, serverIP string, client *websocket.Clien for { select { case <-ticker.C: - _, err := ping(tnet, serverIP, pingTimeout) + // Calculate adaptive timeout based on recent latencies + adaptiveTimeout := pingTimeout + if len(recentLatencies) > 0 { + var sum time.Duration + for _, lat := range recentLatencies { + sum += lat + } + avgLatency := sum / time.Duration(len(recentLatencies)) + // Use 3x average latency as timeout, with minimum of pingTimeout + adaptiveTimeout = avgLatency * 3 + if adaptiveTimeout < pingTimeout { + adaptiveTimeout = pingTimeout + } + if adaptiveTimeout > 15*time.Second { + adaptiveTimeout = 15 * time.Second + } + } + + // Use reliable ping with multiple attempts + maxAttempts := 2 + if consecutiveFailures > 4 { + maxAttempts = 4 // More attempts when connection is unstable + } + + latency, err := reliablePing(tnet, serverIP, adaptiveTimeout, maxAttempts) if err != nil { consecutiveFailures++ - if consecutiveFailures < 4 { + + // Track recent latencies (add a high value for failures) + recentLatencies = append(recentLatencies, adaptiveTimeout) + if len(recentLatencies) > 10 { + recentLatencies = recentLatencies[1:] + } + + if consecutiveFailures < 2 { logger.Debug("Periodic ping failed (%d consecutive failures): %v", consecutiveFailures, err) } else { logger.Warn("Periodic ping failed (%d consecutive failures): %v", consecutiveFailures, err) } - if consecutiveFailures >= 8 && currentInterval < maxInterval { + + // More lenient threshold for declaring connection lost under load + failureThreshold := 4 + if consecutiveFailures >= failureThreshold && currentInterval < maxInterval { if !connectionLost { connectionLost = true - logger.Warn("Connection to server lost. Continuous reconnection attempts will be made.") + logger.Warn("Connection to server lost after %d failures. Continuous reconnection attempts will be made.", consecutiveFailures) stopFunc = client.SendMessageInterval("newt/ping/request", map[string]interface{}{}, 3*time.Second) // Send registration message to the server for backward compatibility err := client.SendMessage("newt/wg/register", map[string]interface{}{ @@ -216,7 +308,7 @@ func startPingCheck(tnet *netstack.Net, serverIP string, client *websocket.Clien } } } - currentInterval = time.Duration(float64(currentInterval) * 1.5) + currentInterval = time.Duration(float64(currentInterval) * 1.3) // Slower increase if currentInterval > maxInterval { currentInterval = maxInterval } @@ -224,9 +316,15 @@ func startPingCheck(tnet *netstack.Net, serverIP string, client *websocket.Clien logger.Debug("Increased ping check interval to %v due to consecutive failures", currentInterval) } } else { + // Track recent latencies + recentLatencies = append(recentLatencies, latency) + if len(recentLatencies) > 10 { + recentLatencies = recentLatencies[1:] + } + if connectionLost { connectionLost = false - logger.Info("Connection to server restored!") + logger.Info("Connection to server restored after %d failures!", consecutiveFailures) if healthFile != "" { err := os.WriteFile(healthFile, []byte("ok"), 0644) if err != nil { @@ -235,12 +333,12 @@ func startPingCheck(tnet *netstack.Net, serverIP string, client *websocket.Clien } } if currentInterval > pingInterval { - currentInterval = time.Duration(float64(currentInterval) * 0.8) + currentInterval = time.Duration(float64(currentInterval) * 0.9) // Slower decrease if currentInterval < pingInterval { currentInterval = pingInterval } ticker.Reset(currentInterval) - logger.Info("Decreased ping check interval to %v after successful ping", currentInterval) + logger.Debug("Decreased ping check interval to %v after successful ping", currentInterval) } consecutiveFailures = 0 } From 663e28329b19ff9948f55f162ed21e4e6da576b6 Mon Sep 17 00:00:00 2001 From: Owen Date: Sun, 13 Jul 2025 16:08:32 -0700 Subject: [PATCH 22/22] Fix typo with _ --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 997745e..dd776f7 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ When Newt receives WireGuard control messages, it will use the information encod - `tls-client-cert` (optional): Client certificate (p12 or pfx) for mTLS. See [mTLS](#mtls) - `docker-socket` (optional): Set the Docker socket to use the container discovery integration - `docker-enforce-network-validation` (optional): Validate the container target is on the same network as the newt process -- `health_file` (optional): Check if connection to WG server (pangolin) is ok. creates a file if ok, removes it if not ok. Can be used with docker healtcheck to restart newt +- `health-file` (optional): Check if connection to WG server (pangolin) is ok. creates a file if ok, removes it if not ok. Can be used with docker healtcheck to restart newt - Example: @@ -78,7 +78,7 @@ services: - --id 31frd0uzbjvp721 - --secret h51mmlknrvrwv8s4r1i210azhumt6isgbpyavxodibx1k2d6 - --endpoint https://example.com - - --health_file /tmp/healthy + - --health-file /tmp/healthy ``` ### Docker Socket Integration