summaryrefslogtreecommitdiffhomepage
path: root/wgengine/netstack/netstack.go
AgeCommit message (Collapse)AuthorFilesLines
2026-04-24wgengine/netstack: absorb all quad-100 traffic locally, never leak to peersJames Tucker1-14/+39
Previously, handleLocalPackets intercepted traffic to the Tailscale service IP (100.100.100.100 / fd7a:115c:a1e0::53) only for an allow-list of ports: TCP 53/80/8080 and UDP 53. Any other port returned filter.Accept, letting the packet fall through to the ACL filter and wireguard-go, which would attempt a peer lookup. No peer owns the quad-100 AllowedIP, so after ~5s pendopen.go would log: open-conn-track: timeout opening ...; no associated peer node This is the common "conntrack error no peer found for 100.100.100.100:853" log spam seen in the wild (e.g. from systemd-resolved or another resolver speculatively trying DoT on quad-100). It also leaks quad-100 packets onto the tailnet. Remove the port allow-list so handleLocalPackets absorbs every quad-100 packet into netstack regardless of IP protocol or port. Traffic never reaches the conntrack / peer-routing layers. With the allow-list gone, acceptTCP needs a corresponding guard: on a quad-100 TCP port we don't serve, execution used to fall through to the isTailscaleIP case (quad-100 is in the tailscale IP range), which rewrote the dial target to 127.0.0.1:<port> and forwardTCP'd the connection to whatever happened to be listening on the host's loopback at that port. Add a hittingServiceIP case that RSTs cleanly instead, placed before the isTailscaleIP fallthrough. TestQuad100UnservedTCPPortDoesNotForward is a new integration test that injects a TCP SYN to 100.100.100.100:853 via handleLocalPackets, stubs forwardDialFunc, and asserts the dialer is not invoked; it catches regressions of the acceptTCP recursion/loopback-redirection case. Fixes #15796 Fixes #19421 Updates #3261 Updates #11305 Signed-off-by: James Tucker <james@tailscale.com>
2026-04-13wgengine/netstack: fix data race on in-flight connection test globalsBrad Fitzpatrick1-7/+9
The maxInFlightConnectionAttemptsForTest and maxInFlightConnectionAttemptsPerClientForTest globals were plain ints read by background gVisor TCP handler goroutines (via wrapTCPProtocolHandler) and written by tstest.Replace cleanup in TestTCPForwardLimits_PerClient. When a gVisor goroutine outlived the test cleanup window, the race detector caught the unsynchronized access. The race-prone code was introduced in c5abbcd4b4d8 (2024-02-26, "wgengine/netstack: add a per-client limit for in-flight TCP forwards") which added both the plain int globals and the TestTCPForwardLimits_PerClient test that writes them via tstest.Replace. It is not obvious why this has only recently started being detected as a data race; likely some combination of gVisor version bumps, Go toolchain scheduler changes, and additional TCP-injecting subtests (e.g. 03461ea7f, 2026-01-30) increased goroutine churn enough to hit the window. Change both globals to atomic.Int32 and replace tstest.Replace (which does non-atomic *target = old on cleanup) with explicit Store/Cleanup pairs. Fixes #19118 Change-Id: Id26ba6fbfb2e4ade319976db80af8e16c7c8778e Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2026-04-08wgengine/netstack: allow UDP listeners to receive traffic on Service VIP ↵Tom Meadows1-0/+28
addresses (#18972) Fixes UDP listeners on VIP Service addresses not receiving inbound traffic. - Modified shouldProcessInbound to check for registered UDP transport endpoints when processing packets to service VIPs - Uses FindTransportEndpoint to determine if a UDP listener exists for the destination VIP/port - Supports both IPv4 and IPv6 The aim was to mirror the existing TCP logic, providing feature parity for UDP-based services on VIP Services. Fixes #18971 Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
2026-03-17wgengine/netstack: add TS_NETSTACK_KEEPALIVE_{IDLE,INTERVAL} envknobsJosef Bacik1-8/+36
Adds envknobs to override the netstack default TCP keepalive idle time (~2h) and probe interval (75s) for forwarded connections. When a tailnet peer goes away without closing its connections (pod deleted, peer removed from the netmap, silent network partition), the forwardTCP io.Copy goroutines block until keepalive fires: the gvisor-side Read waits on a peer that will never send again, and the backend-side Read waits on a backend that is alive and idle. With the netstack default of 7200s idle + 9×75s probes, dead-peer detection takes a little over two hours. Under high-churn forwarding — many short-lived peers, or peers holding thousands of proxied connections that drop at once — stuck goroutines accumulate faster than they clear. The existing SetKeepAlive(true) at this site enables keepalive without setting the timers; the TODO above it noted "a shorter default might be better" and "might be a useful user-tunable". This makes both timers tunable without changing the defaults: unset preserves the ~2h behavior, which is the right trade-off for battery-powered peers. The two knobs are independent — setting one leaves the other at the netstack default. The options are set before SetKeepAlive(true) so the timer arms with the configured values rather than the defaults — matches the order in ipnlocal/local.go for SSH keepalive. Updates #4522 Signed-off-by: Josef Bacik <josefbacik@anthropic.com>
2026-03-13wgengine/netstack: don't register subnet/4via6 TCP flows with proxymapBrad Fitzpatrick1-6/+9
Fixes #18991 Change-Id: I29a609dcd401854026aef4a5ad8d5806c3249ea6 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2026-03-11wgengine{,/magicsock}: add DERP hooks for filtering+sending packetsBrad Fitzpatrick1-7/+17
Add two small APIs to support out-of-tree projects to exchange custom signaling messages over DERP without requiring disco protocol extensions: - OnDERPRecv callback on magicsock.Options / wgengine.Config: called for every non-disco DERP packet before the peer map lookup, allowing callers to intercept packets from unknown peers that would otherwise be dropped. - SendDERPPacketTo method on magicsock.Conn: sends arbitrary bytes to a node key via a DERP region, creating the connection if needed. Thin wrapper around the existing internal sendAddr. Also allow netstack.Start to accept a nil LocalBackend for use cases that wire up TCP/UDP handlers directly without a full LocalBackend. Updates tailscale/corp#24454 Change-Id: I99a523ef281625b8c0024a963f5f5bf5d8792c17 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2026-02-27wgengine/netstack: deliver self-addressed packets via loopbackJames Tucker1-0/+24
When a tsnet.Server dials its own Tailscale IP, TCP SYN packets are silently dropped. In inject(), outbound packets with dst=self fail the shouldSendToHost check and fall through to WireGuard, which has no peer for the node's own address. Fix this by detecting self-addressed packets in inject() using isLocalIP and delivering them back into gVisor's network stack as inbound packets via a new DeliverLoopback method on linkEndpoint. The outbound packet must be re-serialized into a new PacketBuffer because outbound packets have their headers parsed into separate views, but DeliverNetworkPacket expects raw unparsed data. Updates #18829 Signed-off-by: James Tucker <james@tailscale.com>
2026-02-26go.mod: bump gvisorBrad Fitzpatrick1-1/+14
Updates #8043 Change-Id: Ia229ad4f28f2ff20e0bdecb99ca9e1bd0356ad8e Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2026-01-30wgengine/netstack: add local tailscale service IPs to route and terminate ↵KevinLiang101-2/+75
locally (#18461) * wgengine/netstack: add local tailscale service IPs to route and terminate locally This commit adds the tailscales service IPs served locally to OS routes, and make interception to packets so that the traffic terminates locally without making affects to the HA traffics. Fixes tailscale/corp#34048 Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com> * fix test Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com> * add ready field to avoid accessing lb before netstack starts Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com> * wgengine/netstack: store values from lb to avoid acquiring a lock Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com> * add active services to netstack on starts with stored prefs. Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com> * fix comments Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com> * update comments Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com> --------- Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
2026-01-23all: remove AUTHORS file and references to itWill Norris1-1/+1
This file was never truly necessary and has never actually been used in the history of Tailscale's open source releases. A Brief History of AUTHORS files --- The AUTHORS file was a pattern developed at Google, originally for Chromium, then adopted by Go and a bunch of other projects. The problem was that Chromium originally had a copyright line only recognizing Google as the copyright holder. Because Google (and most open source projects) do not require copyright assignemnt for contributions, each contributor maintains their copyright. Some large corporate contributors then tried to add their own name to the copyright line in the LICENSE file or in file headers. This quickly becomes unwieldy, and puts a tremendous burden on anyone building on top of Chromium, since the license requires that they keep all copyright lines intact. The compromise was to create an AUTHORS file that would list all of the copyright holders. The LICENSE file and source file headers would then include that list by reference, listing the copyright holder as "The Chromium Authors". This also become cumbersome to simply keep the file up to date with a high rate of new contributors. Plus it's not always obvious who the copyright holder is. Sometimes it is the individual making the contribution, but many times it may be their employer. There is no way for the proejct maintainer to know. Eventually, Google changed their policy to no longer recommend trying to keep the AUTHORS file up to date proactively, and instead to only add to it when requested: https://opensource.google/docs/releasing/authors. They are also clear that: > Adding contributors to the AUTHORS file is entirely within the > project's discretion and has no implications for copyright ownership. It was primarily added to appease a small number of large contributors that insisted that they be recognized as copyright holders (which was entirely their right to do). But it's not truly necessary, and not even the most accurate way of identifying contributors and/or copyright holders. In practice, we've never added anyone to our AUTHORS file. It only lists Tailscale, so it's not really serving any purpose. It also causes confusion because Tailscalars put the "Tailscale Inc & AUTHORS" header in other open source repos which don't actually have an AUTHORS file, so it's ambiguous what that means. Instead, we just acknowledge that the contributors to Tailscale (whoever they are) are copyright holders for their individual contributions. We also have the benefit of using the DCO (developercertificate.org) which provides some additional certification of their right to make the contribution. The source file changes were purely mechanical with: git ls-files | xargs sed -i -e 's/\(Tailscale Inc &\) AUTHORS/\1 contributors/g' Updates #cleanup Change-Id: Ia101a4a3005adb9118051b3416f5a64a4a45987d Signed-off-by: Will Norris <will@tailscale.com>
2026-01-22tsnet: add support for a user-supplied tun.DeviceJames Tucker1-1/+85
tsnet users can now provide a tun.Device, including any custom implementation that conforms to the interface. netstack has a new option CheckLocalTransportEndpoints that when used alongside a TUN enables netstack listens and dials to correctly capture traffic associated with those sockets. tsnet with a TUN sets this option, while all other builds leave this at false to preserve existing performance. Updates #18423 Signed-off-by: James Tucker <james@tailscale.com>
2025-09-26cmd/tailscaled: start implementing ts_omit_netstackBrad Fitzpatrick1-1/+8
Baby steps. This permits building without much of gvisor, but not all of it. Updates #17283 Change-Id: I8433146e259918cc901fe86b4ea29be22075b32c Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-09-26wgengine/netstack/gro: permit building without GROBrad Fitzpatrick1-1/+1
This only saves ~32KB in the minimal linux/amd64 binary, but it's a step towards permitting not depending on gvisor for small builds. Updates #17283 Change-Id: Iae8da5e9465127de354dbcaf25e794a6832d891b Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-09-26all: don't rebind variables in for loopsAlex Chan1-4/+0
See https://tip.golang.org/wiki/LoopvarExperiment#does-this-mean-i-dont-have-to-write-x--x-in-my-loops-anymore Updates https://github.com/tailscale/tailscale/issues/11058 Signed-off-by: Alex Chan <alexc@tailscale.com>
2025-09-16all: add ts_omit_serve, start making tailscale serve/funnel be modularBrad Fitzpatrick1-7/+13
tailscaled tailscale combined (linux/amd64) 29853147 17384418 31412596 omitting everything + 621570 + 219277 + 554256 .. add serve Updates #17128 Change-Id: I87c2c6c3d3fc2dc026c3de8ef7000a813b41d31c Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-07-07wgengine/netstack: correctly proxy half-closed TCP connectionsNaman Sood1-3/+40
TCP connections are two unidirectional data streams, and if one of these streams closes, we should not assume the other half is closed as well. For example, if an HTTP client closes its write half of the connection early, it may still be expecting to receive data on its read half, so we should keep the server -> client half of the connection open, while terminating the client -> server half. Fixes tailscale/corp#29837. Signed-off-by: Naman Sood <mail@nsood.in>
2025-04-14wgengine/netstack: revert cubic cc to reno cc (#15677)Jordan Whited1-3/+8
Updates google/gvisor#11632 Updates tailscale/corp#27717 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2025-04-08net/{netx,memnet},all: add netx.DialFunc, move memnet Network implBrad Fitzpatrick1-2/+3
This adds netx.DialFunc, unifying a type we have a bazillion other places, giving it now a nice short name that's clickable in editors, etc. That highlighted that my earlier move (03b47a55c7956) of stuff from nettest into netx moved too much: it also dragged along the memnet impl, meaning all users of netx.DialFunc who just wanted netx for the type definition were instead also pulling in all of memnet. So move the memnet implementation netx.Network into memnet, a package we already had. Then use netx.DialFunc in a bunch of places. I'm sure I missed some. And plenty remain in other repos, to be updated later. Updates tailscale/corp#27636 Change-Id: I7296cd4591218e8624e214f8c70dab05fb884e95 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-03-11tsnet,wgengine: fix src to primary Tailscale IP for TCP dialsFran Bull1-0/+43
Ensure that the src address for a connection is one of the primary addresses assigned by Tailscale. Not, for example, a virtual IP address. Updates #14667 Signed-off-by: Fran Bull <fran@tailscale.com>
2025-02-06wgengine/netstack: respond to service IPs in Linux tun modeAdrian Dewhurst1-5/+17
When in tun mode on Linux, AllowedIPs are not automatically added to netstack because the kernel is responsible for handling subnet routes. This ensures that virtual IPs are always added to netstack. When in tun mode, pings were also not being handled, so this adds explicit support for ping as well. Fixes tailscale/corp#26387 Change-Id: I6af02848bf2572701288125f247d1eaa6f661107 Signed-off-by: Adrian Dewhurst <adrian@tailscale.com>
2025-02-06go.mod,wgengine/netstack: use cubic congestion control, bump gvisorJames Tucker1-0/+5
Cubic performs better than Reno in higher BDP scenarios, and enables the use of the hystart++ implementation contributed by Coder. This improves throughput on higher BDP links with a much faster ramp. gVisor is bumped as well for some fixes related to send queue processing and RTT tracking. Updates #9707 Updates #10408 Updates #12393 Updates tailscale/corp#24483 Updates tailscale/corp#25169 Signed-off-by: James Tucker <james@tailscale.com>
2025-02-06wgengine/netstack: disable RACK on all platformsJames Tucker1-10/+8
The gVisor RACK implementation appears to perfom badly, particularly in scenarios with higher BDP. This may have gone poorly noticed as a result of it being gated on SACK, which is not enabled by default in upstream gVisor, but itself has a higher positive impact on performance. Both the RACK and DACK implementations (which are now one) have overlapping non-completion of tasks in their work streams on the public tracker. Updates #9707 Signed-off-by: James Tucker <james@tailscale.com>
2025-01-24cmd/natc,wgengine/netstack: tune buffer size and segment lifetime in natcJames Tucker1-0/+8
Some natc instances have been observed with excessive memory growth, dominant in gvisor buffers. It is likely that the connection buffers are sticking around for too long due to the default long segment time, and uptuned buffer size applied by default in wgengine/netstack. Apply configurations in natc specifically which are a better match for the natc use case, most notably a 5s maximum segment lifetime. Updates tailscale/corp#25169 Signed-off-by: James Tucker <james@tailscale.com>
2025-01-22ipn/ipnlocal: Support TCP and Web VIP servicesKevinLiang101-1/+26
This commit intend to provide support for TCP and Web VIP services and also allow user to use Tun for VIP services if they want to. The commit includes: 1.Setting TCP intercept function for VIP Services. 2.Update netstack to send packet written from WG to netStack handler for VIP service. 3.Return correct TCP hander for VIP services when netstack acceptTCP. This commit also includes unit tests for if the local backend setServeConfig would set correct TCP intercept function and test if a hander gets returned when getting TCPHandlerForDst. The shouldProcessInbound check is not unit tested since the test result just depends on mocked functions. There should be an integration test to cover shouldProcessInbound and if the returned TCP handler actually does what the serveConfig says. Updates tailscale/corp#24604 Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
2024-11-11all: use iterators over slice views moreBrad Fitzpatrick1-4/+2
This gets close to all of the remaining ones. Updates #12912 Change-Id: I9c672bbed2654a6c5cab31e0cbece6c107d8c6fa Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-11-01wgengine/netstack: remove unused taildrive depsBrad Fitzpatrick1-16/+13
A filesystem was plumbed into netstack in 993acf4475b22d693 but hasn't been used since 2d5d6f5403f3. Remove it. Noticed while rebasing a Tailscale fork elsewhere. Updates tailscale/corp#16827 Change-Id: Ib76deeda205ffe912b77a59b9d22853ebff42813 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-10-09syncs: delete Map.Range, update callers to iteratorsBrad Fitzpatrick1-4/+3
Updates #11038 Change-Id: I2819fed896cc4035aba5e4e141b52c12637373b1 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-10-03wgengine/netstack: check userspace ping success on WindowsBrad Fitzpatrick1-0/+33
Hacky temporary workaround until we do #13654 correctly. Updates #13654 Change-Id: I764eaedbb112fb3a34dddb89572fec1b2543fd4a Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-09-10ipnlocal,proxymap,wgengine/netstack: add optional WhoIs/proxymap debugBrad Fitzpatrick1-10/+20
Updates tailscale/corp#20600 Change-Id: I2bb17af0f40603ada1ba4cecc087443e00f9392a Co-authored-by: Maisem Ali <maisem@tailscale.com> Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-08-29net/tstun,wgengine/netstack: implement TCP GRO for local services (#13315)Jordan Whited1-9/+9
Throughput improves substantially when measured via netstack loopback (TS_DEBUG_NETSTACK_LOOPBACK_PORT). Before (d21ebc2): jwhited@i5-12400-2:~$ iperf3 -V -c 100.100.100.100 Starting Test: protocol: TCP, 1 streams, 131072 byte blocks Test Complete. Summary Results: [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 5.77 GBytes 4.95 Gbits/sec 0 sender [ 5] 0.00-10.01 sec 5.77 GBytes 4.95 Gbits/sec receiver After: jwhited@i5-12400-2:~$ iperf3 -V -c 100.100.100.100 Starting Test: protocol: TCP, 1 streams, 131072 byte blocks Test Complete. Summary Results: [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 12.7 GBytes 10.9 Gbits/sec 0 sender [ 5] 0.00-10.00 sec 12.7 GBytes 10.9 Gbits/sec receiver Updates tailscale/corp#22754 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-08-28wgengine/netstack: implement netstack loopback (#13301)Jordan Whited1-11/+54
When the TS_DEBUG_NETSTACK_LOOPBACK_PORT environment variable is set, netstack will loop back (dnat to addressFamilyLoopback:loopbackPort) TCP & UDP flows originally destined to localServicesIP:loopbackPort. localServicesIP is quad-100 or the IPv6 equivalent. Updates tailscale/corp#22713 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-08-27net/tstun: fix gvisor inbound GSO packet injection (#13283)Jordan Whited1-2/+7
buffs[0] was not sized to hold pkt with GSO, resulting in a panic. Updates tailscale/corp#22511 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-08-26wgengine/netstack: re-enable gVisor GSO on Linux (#13269)Jordan Whited1-1/+1
This was previously disabled in 8e42510 due to missing GSO-awareness in tstun, which was resolved in d097096. Updates tailscale/corp#22511 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-08-26net/tstun,wgengine/netstack: make inbound synthetic packet injection ↵Jordan Whited1-1/+20
GSO-aware (#13266) Updates tailscale/corp#22511 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-08-26wgengine/netstack: use types/logger.Logf instead of stdlib log.Printf (#13267)Jordan Whited1-3/+2
Updates #cleanup Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-08-21wgengine/netstack: disable gVisor GSO on Linux (#13215)Jordan Whited1-3/+3
net/tstun.Wrapper.InjectInboundPacketBuffer is not GSO-aware, which can break quad-100 TCP streams as a result. Linux is the only platform where gVisor GSO was previously enabled. Updates tailscale/corp#22511 Updates #13211 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-08-20net/tstun,wgengine{/netstack/gro}: refactor and re-enable gVisor GRO for ↵Jordan Whited1-14/+14
Linux (#13172) In 2f27319baf71681e221904d3a3ffe1badedc8e2e we disabled GRO due to a data race around concurrent calls to tstun.Wrapper.Write(). This commit refactors GRO to be thread-safe, and re-enables it on Linux. This refactor now carries a GRO type across tstun and netstack APIs with a lifetime that is scoped to a single tstun.Wrapper.Write() call. In 25f0a3fc8f6f9cf681bb5afda8e1762816c67a8b we used build tags to prevent importation of gVisor's GRO package on iOS as at the time we believed it was contributing to additional memory usage on that platform. It wasn't, so this commit simplifies and removes those build tags. Updates tailscale/corp#22353 Updates tailscale/corp#22125 Updates #6816 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-08-14wgengine/netstack: disable gVisor TCP GRO for Linux (#13138)Jordan Whited1-2/+3
A SIGSEGV was observed around packet merging logic in gVisor's GRO package. Updates tailscale/corp#22353 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-08-02wgengine/netstack: increase gVisor's TCP send and receive buffer sizes (#12994)Jordan Whited1-3/+43
This commit increases gVisor's TCP max send (4->6MiB) and receive (4->8MiB) buffer sizes on all platforms except iOS. These values are biased towards higher throughput on high bandwidth-delay product paths. The iperf3 results below demonstrate the effect of this commit between two Linux computers with i5-12400 CPUs. 100ms of RTT latency is introduced via Linux's traffic control network emulator queue discipline. The first set of results are from commit f0230ce prior to TCP buffer resizing. gVisor write direction: Test Complete. Summary Results: [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 180 MBytes 151 Mbits/sec 0 sender [ 5] 0.00-10.10 sec 179 MBytes 149 Mbits/sec receiver gVisor read direction: Test Complete. Summary Results: [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.10 sec 337 MBytes 280 Mbits/sec 20 sender [ 5] 0.00-10.00 sec 323 MBytes 271 Mbits/sec receiver The second set of results are from this commit with increased TCP buffer sizes. gVisor write direction: [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 297 MBytes 249 Mbits/sec 0 sender [ 5] 0.00-10.10 sec 297 MBytes 247 Mbits/sec receiver gVisor read direction: [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.10 sec 501 MBytes 416 Mbits/sec 17 sender [ 5] 0.00-10.00 sec 485 MBytes 407 Mbits/sec receiver Updates #9707 Updates tailscale/corp#22119 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-08-02go.mod,net/tstun,wgengine/netstack: implement gVisor TCP GRO for Linux (#12921)Jordan Whited1-29/+8
This commit implements TCP GRO for packets being written to gVisor on Linux. Windows support will follow later. The wireguard-go dependency is updated in order to make use of newly exported IP checksum functions. gVisor is updated in order to make use of newly exported stack.PacketBuffer GRO logic. TCP throughput towards gVisor, i.e. TUN write direction, is dramatically improved as a result of this commit. Benchmarks show substantial improvement, sometimes as high as 2x. High bandwidth-delay product paths remain receive window limited, bottlenecked by gVisor's default TCP receive socket buffer size. This will be addressed in a follow-on commit. The iperf3 results below demonstrate the effect of this commit between two Linux computers with i5-12400 CPUs. There is roughly ~13us of round trip latency between them. The first result is from commit 57856fc without TCP GRO. Starting Test: protocol: TCP, 1 streams, 131072 byte blocks - - - - - - - - - - - - - - - - - - - - - - - - - Test Complete. Summary Results: [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 4.77 GBytes 4.10 Gbits/sec 20 sender [ 5] 0.00-10.00 sec 4.77 GBytes 4.10 Gbits/sec receiver The second result is from this commit with TCP GRO. Starting Test: protocol: TCP, 1 streams, 131072 byte blocks - - - - - - - - - - - - - - - - - - - - - - - - - Test Complete. Summary Results: [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 10.6 GBytes 9.14 Gbits/sec 20 sender [ 5] 0.00-10.00 sec 10.6 GBytes 9.14 Gbits/sec receiver Updates #6816 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-07-31go.mod,net/tstun,wgengine/netstack: implement gVisor TCP GSO for Linux (#12869)Jordan Whited1-3/+6
This commit implements TCP GSO for packets being read from gVisor on Linux. Windows support will follow later. The wireguard-go dependency is updated in order to make use of newly exported GSO logic from its tun package. A new gVisor stack.LinkEndpoint implementation has been established (linkEndpoint) that is loosely modeled after its predecessor (channel.Endpoint). This new implementation supports GSO of monster TCP segments up to 64K in size, whereas channel.Endpoint only supports up to 32K. linkEndpoint will also be required for GRO, which will be implemented in a follow-on commit. TCP throughput from gVisor, i.e. TUN read direction, is dramatically improved as a result of this commit. Benchmarks show substantial improvement through a wide range of RTT and loss conditions, sometimes as high as 5x. The iperf3 results below demonstrate the effect of this commit between two Linux computers with i5-12400 CPUs. There is roughly ~13us of round trip latency between them. The first result is from commit 57856fc without TCP GSO. Starting Test: protocol: TCP, 1 streams, 131072 byte blocks - - - - - - - - - - - - - - - - - - - - - - - - - Test Complete. Summary Results: [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 2.51 GBytes 2.15 Gbits/sec 154 sender [ 5] 0.00-10.00 sec 2.49 GBytes 2.14 Gbits/sec receiver The second result is from this commit with TCP GSO. Starting Test: protocol: TCP, 1 streams, 131072 byte blocks - - - - - - - - - - - - - - - - - - - - - - - - - Test Complete. Summary Results: [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 12.6 GBytes 10.8 Gbits/sec 6 sender [ 5] 0.00-10.00 sec 12.6 GBytes 10.8 Gbits/sec receiver Updates #6816 Signed-off-by: Jordan Whited <jordan@tailscale.com>
2024-07-25wgengine/netstack: simplify netaddrIPFromNetstackIPBrad Fitzpatrick1-4/+2
Updates #cleanup Change-Id: I66878b08a75d44170460cbf33c895277c187bd8d Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-06-18proxymap, various: distinguish between different protocolsAndrew Dunham1-4/+4
Previously, we were registering TCP and UDP connections in the same map, which could result in erroneously removing a mapping if one of the two connections completes while the other one is still active. Add a "proto string" argument to these functions to avoid this. Additionally, take the "proto" argument in LocalAPI, and plumb that through from the CLI and add a new LocalClient method. Updates tailscale/corp#20600 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: I35d5efaefdfbf4721e315b8ca123f0c8af9125fb
2024-06-16net/ipset, wgengine/filter/filtertype: add split-out packagesBrad Fitzpatrick1-3/+4
This moves NewContainsIPFunc from tsaddr to new ipset package. And wgengine/filter types gets split into wgengine/filter/filtertype, so netmap (and thus the CLI, etc) doesn't need to bring in ipset, bart, etc. Then add a test making sure the CLI deps don't regress. Updates #1278 Change-Id: Ia246d6d9502bbefbdeacc4aef1bed9c8b24f54d5 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-06-13wgengine/netstack: add test for #12448Andrew Dunham1-41/+52
This refactors the logic for determining whether a packet should be sent to the host or not into a function, and then adds tests for it. Updates #11304 Updates #12448 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: Ief9afa98eaffae00e21ceb7db073c61b170355e5
2024-06-13wgengine/netstack: fix 4via6 subnet routes (#12454)Irbe Krumina1-2/+11
Fix a bug where, for a subnet router that advertizes 4via6 route, all packets with a source IP matching the 4via6 address were being sent to the host itself. Instead, only send to host packets whose destination address is host's local address. Fixes tailscale/tailscale#12448 Signed-off-by: Irbe Krumina <irbe@tailscale.com> Co-authored-by: Andrew Dunham <andrew@du.nham.ca>
2024-06-02tsnet,wgengine/netstack: add ListenPacket and testsMaisem Ali1-0/+44
This adds a new ListenPacket function on tsnet.Server which acts mostly like `net.ListenPacket`. Unlike `Server.Listen`, this requires listening on a specific IP and does not automatically listen on both V4 and V6 addresses of the Server when the IP is unspecified. To test this, it also adds UDP support to tsdial.Dialer.UserDial and plumbs it through the localapi. Then an associated test to make sure the UDP functionality works from both sides. Updates #12182 Signed-off-by: Maisem Ali <maisem@tailscale.com>
2024-05-16xcode: allow ICMP ping relay on macOS + iOS platforms (#12048)Andrea Gottardo1-47/+3
Fixes tailscale/tailscale#10393 Fixes tailscale/corp#15412 Fixes tailscale/corp#19808 On Apple platforms, exit nodes and subnet routers have been unable to relay pings from Tailscale devices to non-Tailscale devices due to sandbox restrictions imposed on our network extensions by Apple. The sandbox prevented the code in netstack.go from spawning the `ping` process which we were using. Replace that exec call with logic to send an ICMP echo request directly, which appears to work in userspace, and not trigger a sandbox violation in the syslog. Signed-off-by: Andrea Gottardo <andrea@gottardo.me>
2024-05-08wgengine/netstack: handle 4via6 routes that are advertised by the same nodeAndrew Dunham1-30/+107
Previously, a node that was advertising a 4via6 route wouldn't be able to make use of that same route; the packet would be delivered to Tailscale, but since we weren't accepting it in handleLocalPackets, the packet wouldn't be delivered to netstack and would never hit the 4via6 logic. Let's add that support so that usage of 4via6 is consistent regardless of where the connection is initiated from. Updates #11304 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: Ic28dc2e58080d76100d73b93360f4698605af7cb
2024-04-03tailscale: update tailfs functions and vars to use drive naming (#11597)Charlotte Brandhorst-Satzkorn1-16/+16
This change updates all tailfs functions and the majority of the tailfs variables to use the new drive naming. Updates tailscale/corp#16827 Signed-off-by: Charlotte Brandhorst-Satzkorn <charlotte@tailscale.com>