Commit Graph
55 Commits
Author SHA1 Message Date
Claus LensbølandGitHub 978b6a81b2 ipn/ipnlocal: always ReSTUN when starting up without a cache (#19586)
78627c1 introduced starting up and preserving the DERP server from
cache, but also changed it so the initial ReSTUN would not fire when
setting the DERPMap.

Change this so when not working from a cache, the ReSTUN will always
fire during startup.

Updates #19585

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-29 18:56:57 -04:00
Claus LensbølandGitHub be7cce74ba wgengine/userspace: do not fall back to old key on tsmpLearned mismatch (#19575)
The mismatch behaviour of falling back to a previous key could end up
breaking connections when the netmap update took longer than the 2
seconds allowed in controlClient.auto for netmap updates, or if the
controlClient context was canceled. This could end up breaking
legitimate updates to the netmap for disco keys coming from control.

Instead, log the event, and let the connection be reset to that of the
key as that is safer.

Issue found by @bradfitz.

Updates #19574

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-29 13:23:04 -04:00
Claus LensbølandGitHub 78627c132f wgengine/magicsock,ipn/ipnlocal: store and load homeDERP from cache (#19491)
With netmap caching, the home DERP of the self node was neither saved to
the cache or loaded from it, making nodes not stick to a DERP when
starting without a connection to control.

Instead, make sure that when a cache is available, load that cache,
before looking for DERP servers. This is implemented by allowing a skip
of ReSTUN in setting the DERP map (we must have a DERP map before
setting the home DERP), so the DERP from cache will set itself and be
sticky until a connection to control is established.

Making DERP only change when connected to control is handled by existing
code from f072d017bd.

Updates #19490

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-29 10:24:09 -04:00
Claus LensbølandGitHub ee76a7d3f8 wgengine/magicsock: do not send TSMP disco when connected (#19497)
When there is an active connection between devices, do not send new
disco keys via TSMP.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-23 12:23:57 -04:00
Claus LensbølandGitHub 61c95f409c control/controlclient: accept key if last seen on exist node is absent (#19402)
On some nodes (found via natlab), the existing nodes last seen could be
unset. For these cases, we would want to accept the key and write a last
seen. This was breaking the cached netmap natlab tests.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-15 03:53:40 -04:00
Claus LensbølandGitHub 27f1d4c15d control/controlclient: improve filter on netmap updates (#19308)
The previous filters would allow for a handful of subtle issues such as
updating the last seen date when the key or online status had not
changed, and making online keys unconditionally make an engine update.

These have been fixed along side making no change updates from TSMP into
a no-op for the engine so we don't have to reconfigure.

A bunch of additional testing has been added as well.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-14 08:43:07 -04:00
Claus LensbølandGitHub 9e68841939 control/controlclient: avoid calls to ms.netmap() (#19281)
Instead of generating the full netmap, just fetch the peers out the the
existing peers map.

The extra usage was introduced with netmap caching, but there is no need
to call the netmap to get this information, rather the existing peermap
can be used.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-08 09:01:07 -04:00
Claus LensbølandGitHub 9a7f143903 wgengine/userspace: add extra check for tsmp learned keys in engine (#19223)
If an entry in the tsmpLearnedDisco does not match the disco key of the
key currently being processed, overwrite the key, and leave the entry in
the map for later processing.

In reality, this should not happen, but is put in as a safety measure
with logging of the situation so we can replicate the behaviour and
correct it should it happen.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-07 09:11:11 -04:00
Claus LensbølandGitHub d44649a9e4 control/controlclient: add rwlock to peers in mapsession (#19261)
After moving around locks in 4334dfa7d5,
a data race were made possible.

Introduce an RWlock to the mapSession itself for fetching peers.

Fixes #19260

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-07 08:52:55 -04:00
Claus LensbølandGitHub ffaebd71fb control/controlclient: filter out disco updates from full map (#19220)
When getting a full map from control, disco keys for the nodes will also
be delivered. When communicating with a peer that is running without
being connected to control, and having that connection running based on
a TSMP learned disco key, we need to avoid overwriting the disco key for
that peer with the stale one control knows about.

Add a filter that filteres out keys from control, and replace them with
the TSMP learned disco keys.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-02 13:08:01 -04:00
Claus LensbølandGitHub c76113ac75 wgengine/magicsock: send out disco keys over TSMP periodically (#19212)
Instead of sending out disco keys via TSMP once, send them out in
intervals of 60+ seconds. The trigger is still callmemaaybe and the keys
will not be send if no direct connection needs to be established.

This fixes a case where a node can have stale keys but have communicated
with the other peer before, leading to an infinite DERP state.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-01 17:20:03 -04:00
Claus LensbølandGitHub 4334dfa7d5 control/controlclient: take mapsession and release lock early in sub (#19192)
The disco key subscriber could deadlock in a scenario where a self node
update came through the control path into the mapSession after the disco
key subscriber had taken the lock, but before it had pushed the netmap
change, as both the subscriber and onSelfNodeChanged needs the
controlclient lock.

The subscriber can safely take the mapsession as the changequeue has its
own lock for inserting records, and also checks if the queue has been
closed before inserting.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-31 12:47:13 -04:00
Claus LensbølandGitHub bf467727fc control/controlclient,ipn/ipnlocal,wgengine: avoid restarting wireguard when key is learned via tsmp (#19142)
When disco keys are learned on a node that is connected to control and
has a mapSession, wgengine will see the key as having changed, and
assume that any existing connections will need to be reset.

For keys learned via TSMP, the connection should not be reset as that
key is learned via an active wireguard connection. If wgengine resets
that connetion, a 15s timeout will occur.

This change adds a map to track new keys coming in via TSMP, and removes
them from the list of keys that needs to trigger wireguard resets. This
is done with an interface chain from controlclient down via localBackend
to userspaceEngine via the watchdog.

Once a key has been actively used for preventing a wireguard reset, the
key is removed from the map.

If mapSession becomes a long lived process instead of being dependent on
having a connection to control. This interface chain can be removed, and
the event sequence from wrap->controlClient->userspaceEngine, can be
changed to wrap->userspaceEngine->controlClient as we know the map will
not be gunked up with stale TSMP entries.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-30 14:26:08 -04:00
Claus LensbølandGitHub 9a4a2db0fc control/controlclient: handle errors in rememberLastNetmapUpdator (#19112)
If errors occured, the updater could end up deadlocked.

Closing the done channel rather than adding to it, fixes a deadlock in
the corp tests.

Updates #19111

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-24 20:36:34 -04:00
Claus LensbølandGitHub 87ec3235d9 control/controlclient: allow multiple non-streaming map requests (#19106)
A client with an active streaming session would break if using the same
client for a non-streaming session. Allow the client 1 streaming and n
non-streaming sessions at the same time.

Fixes #19105

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-24 14:19:21 -04:00
Claus LensbølandGitHub 85bb5f84a5 wgengine/magicsock,control/controlclient: do not overwrite discokey with old key (#18606)
When a client starts up without being able to connect to control, it
sends its discoKey to other nodes it wants to communicate with over
TSMP. This disco key will be a newer key than the one control knows
about.

If the client that can connect to control gets a full netmap, ensure
that the disco key for the node not connected to control is not
overwritten with the stale key control knows about.

This is implemented through keeping track of mapSession and use that for
the discokey injection if it is available. This ensures that we are not
constantly resetting the wireguard connection when getting the wrong
keys from control.

This is implemented as:
 - If the key is received via TSMP:
   - Set lastSeen for the peer to now()
   - Set online for the peer to false
 - When processing new keys, only accept keys where either:
   - Peer is online
   - lastSeen is newer than existing last seen

If mapSession is not available, as in we are not yet connected to
control, punt down the disco key injection to magicsock.

Ideally, we will want to have mapSession be long lived at some point in
the near future so we only need to inject keys in one location and then
also use that for testing and loading the cache, but that is a yak for
another PR.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-20 08:56:27 -04:00
Claus LensbølandGitHub 2534bc3202 net/tstun: do not write when Wrapper is closed (#19038)
Two methods could deadlock during shutdown when closing the wrapper.

Ensure that the writers are aware of the wrapper being closed.

Fixes #19037

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-18 17:53:34 -04:00
Claus LensbølandGitHub 9657a93217 tstest/natlab: add test for no control and rotated disco key (#18261)
Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-05 16:00:36 -05:00
Claus LensbølandGitHub 1b53c00f2b clientupdate,net/tstun: add support for OpenWrt 25.12.0 using apk (#18545)
OpenWrt is changing to using alpine like `apk` for package installation
over its previous opkg. Additionally, they are not using the same repo
files as alpine making installation fail.

Add support for the new repository files and ensure that the required
package detection system uses apk.

Updates #18535

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-05 13:39:07 -05:00
Claus LensbølandBrad Fitzpatrick ea1f1616b9 .github/workflows: enable natlab in CI
After fixing the flakey tests in #18811 and #18814 we can enable running
the natlab testsuite running on CI generally.

Fixes #18810

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-04 15:02:07 -08:00
Claus LensbølandGitHub 2d21dd46cd wgengine/magicsoc,net/tstun: put disco key advertisement behind a nob (#18857)
To be less spammy in stable, add a nob that disables the creation and
processing of TSMPDiscoKeyAdvertisements until we have a proper rollout
mechanism.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-03 09:04:37 -05:00
Claus LensbølandGitHub 5ac35b665b client/systray: add installer for a freedesktop autostart file (#18767)
Adds freedesktop as an option for installing autostart desktop files for
starting the systray application.

Fixes #18766

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-02-26 12:59:45 -05:00
Claus LensbølandGitHub 151644f647 wgengine: send disco key via TSMP on first contact (#18215)
When we have not yet communicated with a peer, send a
TSMPDiscoAdvertisement to let the peer know of our disco key. This is in
most cases redundant, but will allow us to set up direct connections
when the client cannot access control.

Some parts taken from: #18073

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-01-22 14:50:24 -05:00
c870d3811d net/{packet,tstun},wgengine: update disco key when receiving via TSMP (#18158)
When receiving a TSMPDiscoAdvertisement from peer, update the discokey
for said peer.

Some parts taken from: https://github.com/tailscale/tailscale/pull/18073/

Updates #12639

Co-authored-by: James Tucker <james@tailscale.com>
2025-12-10 14:27:20 -05:00
Claus LensbølandGitHub 1dfdee8521 net/dns: retrample resolve.conf when another process has trampled it (#18069)
When using the resolve.conf file for setting DNS, it is possible that
some other services will trample the file and overwrite our set DNS
server. Experiments has shown this to be a racy error depending on how
quickly processes start.

Make an attempt to trample back the file a limited number of times if
the file is changed.

Updates #16635

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-12-09 14:55:26 -05:00
Claus LensbølandGitHub d349370e55 client/systray: change systray to start after graphical.target (#18138)
The service was starting after systemd itself, and while this
surprisingly worked for some situations, it broke for others.

Change it to start after a GUI has been initialized.

Updates #17656

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-12-05 11:05:49 -05:00
c54d243690 net/tstun: add TSMPDiscoAdvertisement to TSMPPing (#17995)
Adds a new types of TSMP messages for advertising disco keys keys
to/from a peer, and implements the advertising triggered by a TSMP ping.

Needed as part of the effort to cache the netmap and still let clients
connect without control being reachable.

Updates #12639

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
Co-authored-by: James Tucker <james@tailscale.com>
2025-11-25 15:35:38 -05:00
Claus LensbølandGitHub e7f5ca1d5e wgengine/userspace: run link change subscribers in eventqueue (#18024)
Updates #17996

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-11-21 14:49:37 -05:00
Claus LensbølandGitHub fd0e541e5d net/tsdial: do not panic if setting the same eventbus twice (#17640)
Updates #17638

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-10-24 15:00:55 -04:00
Claus LensbølandGitHub 7418583e47 health: compare warnable codes to avoid errors on release branch (#17637)
This compares the warnings we actually care about and skips the unstable
warnings and the changes with no warnings.

Fixes #17635

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-10-24 12:08:35 -04:00
Claus LensbølandGitHub ab435ce3a6 client/systray: warn users launching the application with sudo (#17595)
If users start the application with sudo, DBUS is likely not available
or will not have the correct endpoints. We want to warn users when doing
this.

Closes #17593

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-10-20 15:24:39 -04:00
Claus LensbølandGitHub 005e264b54 util/eventbus/eventbustest: add support for synctest instead of timers (#17522)
Before synctest, timers was needed to allow the events to flow into the
test bus. There is still a timer, but this one is not derived from the
test deadline and it is mostly arbitrary as synctest will render it
practically non-existent.

With this approach, tests that do not need to test for the absence of
events do not rely on synctest.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-10-10 15:33:30 -04:00
Claus LensbølandGitHub 57bd875856 control/controlclient: add missing comment (#17498)
Updates #cleanup

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-10-08 11:36:38 -04:00
Claus LensbølandGitHub 63f7a400a8 wgengine/{magicsock,userspace,router}: move portupdates to the eventbus (#17423)
Also pull out interface method only needed in Linux.

Instead of having userspace do the call into the router, just let the
router pick up the change itself.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-10-07 09:30:27 -04:00
Claus LensbølandGitHub ce752b8a88 net/netmon: remove usage of direct callbacks from netmon (#17292)
The callback itself is not removed as it is used in other repos, making
it simpler for those to slowly transition to the eventbus.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-10-01 14:59:38 -04:00
Claus LensbølandGitHub 9ae8155bab cmol/pprof health (#17303)
health: ensure timers are cleaned up

Updates tailscale/corp#32696

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-09-26 17:30:24 -04:00
Claus LensbølandGitHub f67ad67c6f control/controlclient: switch ID to be incrementing instead of random (#17230)
Also cleans up a a few comments.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-09-22 13:14:55 -04:00
Claus LensbølandGitHub 6e128498a7 controlclient/auto: switch eventbus to using a monitor (#17205)
Only changes how the go routine consuming the events starts and stops,
not what it does.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-09-22 09:16:13 -04:00
Claus LensbølandGitHub 009d702adf health: remove direct callback and replace with eventbus (#17199)
Pulls out the last callback logic and ensures timers are still running.

The eventbustest package is updated support the absence of events.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-09-19 14:58:37 -04:00
Claus LensbølandGitHub df362d0a08 net/netmon: make ChangeDelta event not a pointer (#17112)
This makes things work slightly better over the eventbus.

Also switches ipnlocal to use the event over the eventbus instead of the
direct callback.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-09-17 10:49:41 -04:00
Claus LensbølandGitHub 2015ce4081 health,ipn/ipnlocal: introduce eventbus in heath.Tracker (#17085)
The Tracker was using direct callbacks to ipnlocal. This PR moves those
to be triggered via the eventbus.

Additionally, the eventbus is now closed on exit from tailscaled
explicitly, and health is now a SubSystem in tsd.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-09-16 11:25:29 -04:00
Claus LensbølandGitHub b816fd7117 control/controlclient: introduce eventbus messages instead of callbacks (#16956)
This is a small introduction of the eventbus into controlclient that
communicates with mainly ipnlocal. While ipnlocal is a complicated part
of the codebase, the subscribers here are from the perspective of
ipnlocal already called async.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-09-15 10:36:17 -04:00
Claus LensbølandGitHub fafb514538 client/systray: go back to using upstream library (#16938)
We had a fix in a local branch, but upstream has merged it now.

Updates #1708

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-08-25 08:58:12 -04:00
Claus LensbølandGitHub 5297dc3baf cmd/tailscale/cli: move systray configuration to tailscale configure (#16817)
Updates #1708

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-08-08 16:12:11 -04:00
Claus LensbølandGitHub 3fe022877a client/systray: temporarily replace systray module (#16807)
We are waiting for a PR to be reviewed upstream.

https://github.com/fyne-io/systray/pull/100

Updates #1708

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-08-07 16:02:47 -04:00
Claus LensbølandGitHub 89954fbceb client/systray: add startup script generator for systemd (#16801)
Updates #1708

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-08-07 11:51:15 -04:00
Claus LensbølandGitHub 5bb42e3018 wgengine/router: rely on events for deleted IP rules (#16744)
Adds the eventbus to the router subsystem.

The event is currently only used on linux.

Also includes facilities to inject events into the bus.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-08-05 08:31:51 -04:00
Claus LensbølandWill Norris d1ceb62e27 client/systray: look for ubuntu gnome
Ubuntu gnome has a different name on at least 25.04.

Updates #1708

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-07-18 09:10:00 -07:00
Claus LensbølandGitHub d334d9ba07 client/local,cmd/tailscale/cli,ipn/localapi: expose eventbus graph (#16597)
Make it possible to dump the eventbus graph as JSON or DOT to both debug
and document what is communicated via the bus.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-07-18 10:55:17 -04:00
Claus LensbølandGitHub fbc4c34cf7 ipn/localapi: do not break client on event marshalling errors (#16503)
Errors were mashalled without the correct newlines. Also, they could
generally be mashalled with more data, so an intermediate was introduced
to make them slightly nicer to look at.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-07-10 03:04:29 -04:00
Claus LensbølandGitHub 53f67c4396 util/eventbus: fix docstrings (#16401)
Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-06-27 10:03:56 -04:00
Claus LensbølandGitHub 37eca1785c net/netmon: add tests for the events over the eventbus (#16382)
Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-06-25 14:44:01 -04:00
Claus LensbølandGitHub f2f1236ad4 util/eventbus: add test helpers to simplify testing events (#16294)
Instead of every module having to come up with a set of test methods for
the event bus, this handful of test helpers hides a lot of the needed
setup for the testing of the event bus.

The tests in portmapper is also ported over to the new helpers.

Updates #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-06-25 09:00:34 -04:00
Claus LensbølandGitHub 6010812f0c ipn/localapi,client/local: add debug watcher for bus events (#16239)
Updates: #15160

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-06-11 14:22:30 -04:00
Claus LensbølandGitHub 3f7a9f82e3 wgengine/magicsock: fix bpf fragmentation jump offsets (#16204)
Fragmented datagrams would be processed instead of being dumped right
away. In reality, thse datagrams would be dropped anyway later so there
should functionally not be any change. Additionally, the feature is off
by default.

Closes #16203

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2025-06-06 11:42:33 -04:00