Commit Graph

1219 Commits

Author SHA1 Message Date
Viktor Liu
b0f5d78df1 Ignore v6 exit node notification 2026-04-28 12:10:39 +02:00
Viktor Liu
e19d0c7d77 Merge branch 'main' into proto-ipv6-overlay
# Conflicts:
#	client/firewall/iptables/manager_linux.go
#	client/firewall/nftables/manager_linux.go
#	client/firewall/nftables/router_linux.go
2026-04-23 11:48:15 +02:00
Viktor Liu
801de8c68d [client] Add TTL-based refresh to mgmt DNS cache via handler chain (#5945) 2026-04-22 15:10:14 +02:00
Zoltan Papp
1165058fad [client] fix port collision in TestUpload (#5950)
* [debug] fix port collision in TestUpload

TestUpload hardcoded :8080, so it failed deterministically when anything
was already on that port and collided across concurrent test runs.
Bind a :0 listener in the test to get a kernel-assigned free port, and
add Server.Serve so tests can hand the listener in without reaching
into unexported state.

* [debug] drop test-only Server.Serve, use SERVER_ADDRESS env

The previous commit added a Server.Serve method on the upload-server,
used only by TestUpload. That left production with an unused function.
Reserve an ephemeral loopback port in the test, release it, and pass
the address through SERVER_ADDRESS (which the server already reads).
A small wait helper ensures the server is accepting connections before
the upload runs, so the close/rebind gap does not cause a false failure.
2026-04-21 19:07:20 +02:00
Zoltan Papp
2fb50aef6b [client] allow UDP packet loss in TestICEBind_HandlesConcurrentMixedTraffic (#5953)
The test writes 500 packets per family and asserted exact-count
delivery within a 5s window, even though its own comment says "Some
packet loss is acceptable for UDP". On FreeBSD/QEMU runners the writer
loops cannot always finish all 500 before the 5s deadline closes the
readers (we have seen 411/500 in CI).

The real assertion of this test is the routing check — IPv4 peer only
gets v4- packets, IPv6 peer only gets v6- packets — which remains
strict. Replace the exact-count assertions with a >=80% delivery
threshold so runner speed variance no longer causes false failures.
2026-04-21 19:05:58 +02:00
Viktor Liu
064ec1c832 [client] Trust wg interface in firewalld to bypass owner-flagged chains (#5928) 2026-04-21 17:57:16 +02:00
Viktor Liu
75e408f51c [client] Prefer systemd-resolved stub over file mode regardless of resolv.conf header (#5935) 2026-04-21 17:56:56 +02:00
Zoltan Papp
5a89e6621b [client] Supress ICE signaling (#5820)
* [client] Suppress ICE signaling and periodic offers in force-relay mode

When NB_FORCE_RELAY is enabled, skip WorkerICE creation entirely,
suppress ICE credentials in offer/answer messages, disable the
periodic ICE candidate monitor, and fix isConnectedOnAllWay to
only check relay status so the guard stops sending unnecessary offers.

* [client] Dynamically suppress ICE based on remote peer's offer credentials

Track whether the remote peer includes ICE credentials in its
offers/answers. When remote stops sending ICE credentials, skip
ICE listener dispatch, suppress ICE credentials in responses, and
exclude ICE from the guard connectivity check. When remote resumes
sending ICE credentials, re-enable all ICE behavior.

* [client] Fix nil SessionID panic and force ICE teardown on relay-only transition

Fix nil pointer dereference in signalOfferAnswer when SessionID is nil
(relay-only offers). Close stale ICE agent immediately when remote peer
stops sending ICE credentials to avoid traffic black-hole during the
ICE disconnect timeout.

* [client] Add relay-only fallback check when ICE is unavailable

Ensure the relay connection is supported with the peer when ICE is disabled to prevent connectivity issues.

* [client] Add tri-state connection status to guard for smarter ICE retry (#5828)

* [client] Add tri-state connection status to guard for smarter ICE retry

Refactor isConnectedOnAllWay to return a ConnStatus enum (Connected,
Disconnected, PartiallyConnected) instead of a boolean. When relay is
up but ICE is not (PartiallyConnected), limit ICE offers to 3 retries
with exponential backoff then fall back to hourly attempts, reducing
unnecessary signaling traffic. Fully disconnected peers continue to
retry aggressively. External events (relay/ICE disconnect, signal/relay
reconnect) reset retry state to give ICE a fresh chance.

* [client] Clarify guard ICE retry state and trace log trigger

Split iceRetryState.attempt into shouldRetry (pure predicate) and
enterHourlyMode (explicit state transition) so the caller in
reconnectLoopWithRetry reads top-to-bottom. Restore the original
trace-log behavior in isConnectedOnAllWay so it only logs on full
disconnection, not on the new PartiallyConnected state.

* [client] Extract pure evalConnStatus and add unit tests

Split isConnectedOnAllWay into a thin method that snapshots state and
a pure evalConnStatus helper that takes a connStatusInputs struct, so
the tri-state decision logic can be exercised without constructing
full Worker or Handshaker objects. Add table-driven tests covering
force-relay, ICE-unavailable and fully-available code paths, plus
unit tests for iceRetryState budget/hourly transitions and reset.

* [client] Improve grammar in logs and refactor ICE credential checks
2026-04-21 15:52:08 +02:00
Viktor Liu
3537e2234f Fix manager_test.go: use netip.MustParseAddr for PeerSSHInfo.IP 2026-04-20 19:58:59 +02:00
Viktor Liu
d2aaadbb8c Replace deprecated iptables --set with --match-set in ACL ipset match 2026-04-20 19:56:45 +02:00
Viktor Liu
4506f82b2d Merge branch 'main' into proto-ipv6-overlay 2026-04-20 19:45:14 +02:00
Zoltan Papp
3098f48b25 [client] fix ios network addresses mac filter (#5906)
* fix(client): skip MAC address filter for network addresses on iOS

iOS does not expose hardware (MAC) addresses due to Apple's privacy
restrictions (since iOS 14), causing networkAddresses() to return an
empty list because all interfaces are filtered out by the HardwareAddr
check. Move networkAddresses() to platform-specific files so iOS can
skip this filter.
2026-04-20 11:49:38 +02:00
Zoltan Papp
7f023ce801 [client] Android debug bundle support (#5888)
Add Android debug bundle support with Troubleshoot UI
2026-04-20 11:26:30 +02:00
Michael Uray
e361126515 [client] Fix WGIface.Close deadlock when DNS filter hook re-enters GetDevice (#5916)
WGIface.Close() took w.mu and held it across w.tun.Close(). The
underlying wireguard-go device waits for its send/receive goroutines to
drain before Close() returns, and some of those goroutines re-enter
WGIface during shutdown. In particular, the userspace packet filter DNS
hook in client/internal/dns.ServiceViaMemory.filterDNSTraffic calls
s.wgInterface.GetDevice() on every packet, which also needs w.mu. With
the Close-side holding the mutex, the read goroutine blocks in
GetDevice and Close waits forever for that goroutine to exit:

  goroutine N (TestDNSPermanent_updateUpstream):
    WGIface.Close -> holds w.mu -> tun.Close -> sync.WaitGroup.Wait
  goroutine M (wireguard read routine):
    FilteredDevice.Read -> filterOutbound -> udpHooksDrop ->
    filterDNSTraffic.func1 -> WGIface.GetDevice -> sync.Mutex.Lock

This surfaces as a 5 minute test timeout on the macOS Client/Unit
CI job (panic: test timed out after 5m0s, running tests:
TestDNSPermanent_updateUpstream).

Release w.mu before calling w.tun.Close(). The other Close steps
(wgProxyFactory.Free, waitUntilRemoved, Destroy) do not mutate any
fields guarded by w.mu beyond what Free() already does, so the lock
is not needed once the tun has started shutting down. A new unit test
in iface_close_test.go uses a fake WGTunDevice to reproduce the
deadlock deterministically without requiring CAP_NET_ADMIN.
2026-04-20 10:36:19 +02:00
Viktor Liu
95213f7157 [client] Use Match host+exec instead of Host+Match in SSH client config (#5903) 2026-04-20 10:24:11 +02:00
Viktor Liu
cec21034e8 [client] Reconcile external nft accept rules on external changes (#5912) 2026-04-20 10:23:44 +02:00
Viktor Liu
2e0e3a3601 [client] Replace exclusion routes with scoped default + IP_BOUND_IF on macOS (#5918) 2026-04-20 10:01:01 +02:00
Viktor Liu
02c0b20f21 Move IPv6 blackhole from notifier to platform tun (java/swift) 2026-04-18 12:28:16 +02:00
Viktor Liu
0c9f4706b2 Merge branch 'main' into proto-ipv6-overlay 2026-04-17 05:45:43 +02:00
Maycon Santos
53b04e512a [management] Reuse a single cache store across all management server consumers (#5889)
* Add support for legacy IDP cache environment variable

* Centralize cache store creation to reuse a single Redis connection pool

Each cache consumer (IDP cache, token store, PKCE store, secrets manager,
EDR validator) was independently calling NewStore, creating separate Redis
clients with their own connection pools — up to 1400 potential connections
from a single management server process.

Introduce a shared CacheStore() singleton on BaseServer that creates one
store at boot and injects it into all consumers. Consumer constructors now
receive a store.StoreInterface instead of creating their own.

For Redis mode, all consumers share one connection pool (1000 max conns).
For in-memory mode, all consumers share one GoCache instance.

* Update management-integrations module to latest version

* sync go.sum

* Export `GetAddrFromEnv` to allow reuse across packages

* Update management-integrations module version in go.mod and go.sum

* Update management-integrations module version in go.mod and go.sum
2026-04-16 16:04:53 +02:00
Viktor Liu
633dde8d1f [client] Reconnect conntrack netlink listener on error (#5885) 2026-04-16 22:30:36 +09:00
Michael Uray
7e4542adde fix(client): populate NetworkAddresses on iOS for posture checks (#5900)
The iOS GetInfo() function never populated NetworkAddresses, causing
the peer_network_range_check posture check to fail for all iOS clients.

This adds the same networkAddresses() call that macOS, Linux, Windows,
and FreeBSD already use.

Fixes: #3968
Fixes: #4657
2026-04-16 14:25:55 +02:00
Viktor Liu
d4c61ed38b [client] Add mangle FORWARD guard to prevent Docker DNAT bypass of ACL rules (#5697) 2026-04-16 14:02:52 +02:00
Viktor Liu
6b540d145c [client] Add --disable-networks flag to block network selection (#5896) 2026-04-16 14:02:31 +02:00
Viktor Liu
95bc01e48f [client] Allow clearing saved service env vars with --service-env "" (#5893) 2026-04-15 19:22:08 +02:00
Viktor Liu
0d86de47df [client] Add PCP support (#5219) 2026-04-15 11:43:16 +02:00
Viktor Liu
4eed459f27 [client] Fix DNS resolution with userspace WireGuard and kernel firewall (#5873) 2026-04-13 16:23:57 +02:00
Viktor Liu
f86ecea26f Merge remote-tracking branch 'origin/main' into proto-ipv6-overlay
Resolve conflict in setupAndroidRoutes: merge IPv6 fake IP route
with the explicit fake IP route storage from #5865.

Notifier now stores a slice of fake IP routes (v4 + v6) via
SetFakeIPRoutes to preserve the stale route re-injection fix.
2026-04-13 11:39:08 +02:00
Zoltan Papp
7483fec048 Fix Android internet blackhole caused by stale route re-injection on TUN rebuild (#5865)
extraInitialRoutes() was meant to preserve only the fake IP route
(240.0.0.0/8) across TUN rebuilds, but it re-injected any initial
route missing from the current set. When the management server
advertised exit node routes (0.0.0.0/0) that were later filtered
by the route selector, extraInitialRoutes() re-added them, causing
the Android VPN to capture all traffic with no peer to handle it.

Store the fake IP route explicitly and append only that in notify(),
removing the overly broad initial route diffing.
2026-04-13 09:38:38 +02:00
Viktor Liu
d1070a41a8 Regenerate proto files with matching tool versions from main 2026-04-11 18:49:41 +02:00
Viktor Liu
51d1edf8b2 Resolve tracer 'self' to v6 overlay address when peer is IPv6
The packet tracer resolved 'self' to the v4 overlay address
unconditionally, causing "mixed address families" errors when tracing
v6 traffic. Pick the self address matching the peer's address family.

Add Engine.GetWgV6Addr() and rework parseAddress into
resolveTraceAddresses which parses the non-self address first to
determine the family, then resolves self accordingly.
2026-04-10 13:28:32 +02:00
Viktor Liu
4fc910031b Check chain existence before deleting NAT OUTPUT jump rule
The cleanup path tried to delete the jump rule to NETBIRD-NAT-OUTPUT
unconditionally, producing a noisy debug log when the chain was never
created (common for the v6 router when no OutputDNAT rules exist).
Check ChainExists first, consistent with the chain deletion loop
below.
2026-04-10 13:21:05 +02:00
Viktor Liu
4b298fb53c Fix legacy dynamic route NAT missing v6 duplicate
The v6 NAT duplication only triggered for DomainSet destinations
(modern DNS path). Legacy dynamic routes use a 0.0.0.0/0 prefix
destination, so the v6 NAT rule was never created.

Add a Dynamic field to RouterPair so the firewall manager can
distinguish dynamic routes from exit nodes (both use /0 prefixes).
Set it from route.IsDynamic() in routeToRouterPair and propagate
through GetInversePair. Both nftables and iptables managers check
pair.Dynamic instead of destination shape.

Also accumulate errors in RemoveNatRule so v6 cleanup is attempted
even if v4 removal fails.
2026-04-10 13:09:15 +02:00
Viktor Liu
567f36b07e Fix legacy dynamic route NAT missing v6 duplicate
The legacy DNS resolver path creates NAT pairs with destination
0.0.0.0/0 (a prefix, not a DomainSet). The v6 NAT duplication only
triggered for DomainSets, so legacy dynamic routes never got a v6
NAT rule.

Extract NeedsV6NATDuplicate and ToV6NatPair helpers that detect both
DomainSets and the v4 default wildcard 0.0.0.0/0. Both nftables and
iptables managers now use these for Add/RemoveNatRule, ensuring v6
NAT duplication works for both modern and legacy DNS resolver paths.
2026-04-10 12:59:35 +02:00
Viktor Liu
8ddbcf6c5b Fix dynamic route v6 NAT rule not cleaned up on removal
removeFromServerNetwork and CleanUp hardcoded useNewDNSRoute=false
when building the router pair for RemoveNatRule. This meant the
destination was a Prefix (0.0.0.0/0) instead of a DomainSet, so the
IsSet() branch in RemoveNatRule that removes the v6 duplicate never
triggered. The v6 NAT rule leaked until the next full Reset.

Store useNewDNSRoute on the Router from UpdateRoutes and use it
consistently in removeFromServerNetwork and CleanUp, making add
and remove symmetric.
2026-04-10 12:50:09 +02:00
Viktor Liu
2f5d9fc0cd Add IPv6 dispatch for OutputDNAT, fix v6 guard pattern, rename DNAT params
- Add IPv6 router dispatch to AddOutputDNAT/RemoveOutputDNAT in both
  nftables and iptables managers (was hardcoded to v4 router only).
- Fix all DNAT and AddDNATRule dispatch methods to check Is6() first,
  then error with ErrIPv6NotInitialized if v6 components are missing.
  Previously the hasIPv6() && Is6() pattern silently fell through to
  the v4 router for v6 addresses when v6 was not initialized.
- Add ErrIPv6NotInitialized sentinel error, replace all ad-hoc
  "IPv6 not initialized" format strings across both managers.
- Rename sourcePort/targetPort to originalPort/translatedPort in all
  DNAT method signatures to reflect actual DNAT semantics.
- Remove stale "localAddr must be IPv4" comments from interface.
2026-04-10 12:32:41 +02:00
Viktor Liu
2a34f173c5 Anonymize SourcePrefixes in firewall rule debug output 2026-04-10 06:55:10 +02:00
Viktor Liu
6c5ff88569 Return error from EncodePrefix instead of silently clamping bits 2026-04-10 06:51:55 +02:00
Viktor Liu
456298864c Merge remote-tracking branch 'origin/main' into proto-ipv6-overlay
# Conflicts:
#	client/firewall/iptables/manager_linux.go
#	client/firewall/nftables/manager_linux.go
2026-04-10 06:51:49 +02:00
Viktor Liu
6e05a2ebe9 Fix CodeRabbit review issues from IPv6 overlay PR (#5839) 2026-04-10 09:12:35 +08:00
Viktor Liu
d2cdc0efec [client] Use native firewall for peer ACLs in userspace WireGuard mode (#5668) 2026-04-10 09:12:13 +08:00
Viktor Liu
f484835292 Use net.JoinHostPort and net.SplitHostPort for IPv6-safe host:port handling (#5836) 2026-04-10 09:10:57 +08:00
Viktor Liu
ac816a8382 Merge remote-tracking branch 'origin/main' into proto-ipv6-overlay 2026-04-09 11:58:06 +02:00
Viktor Liu
1c4e5e71d7 [client] Add IPv6 support to ACL manager, USP filter, and forwarder (#5688) 2026-04-09 10:56:08 +02:00
Viktor Liu
94a36cb53e [client] Handle UPnP routers that only support permanent leases (#5826) 2026-04-08 17:59:59 +02:00
Viktor Liu
c7ba931466 [client] Populate network addresses in FreeBSD system info (#5827) 2026-04-08 17:14:16 +02:00
Viktor Liu
413d95b740 [client] Include service.json in debug bundle (#5825)
* Include service.json in debug bundle

* Add tests for service params sanitization logic
2026-04-08 21:10:31 +08:00
Viktor Liu
332c624c55 [client] Don't abort UI debug bundle when up/down fails (#5780) 2026-04-08 10:33:46 +02:00
Viktor Liu
dc160aff36 [client] Fix SSH proxy stripping shell quoting from forwarded commands (#5669) 2026-04-08 10:25:57 +02:00
Viktor Liu
d33cd4c95b [client] Add NAT-PMP/UPnP support (#5202) 2026-04-08 15:29:32 +08:00