<feed xmlns='http://www.w3.org/2005/Atom'>
<title>tailscale/wgengine/magicsock/endpoint.go, branch bradfitz/rm_lazy_wg</title>
<subtitle>The easiest, most secure way to use WireGuard and 2FA</subtitle>
<id>http://git.waynecole.info/tailscale/atom?h=bradfitz%2Frm_lazy_wg</id>
<link rel='self' href='http://git.waynecole.info/tailscale/atom?h=bradfitz%2Frm_lazy_wg'/>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/'/>
<updated>2026-04-25T01:53:13Z</updated>
<entry>
<title>wgengine, all: remove LazyWG, use wireguard-go callback API for on-demand peers</title>
<updated>2026-04-25T01:53:13Z</updated>
<author>
<name>Brad Fitzpatrick</name>
<email>bradfitz@tailscale.com</email>
</author>
<published>2026-04-15T00:49:12Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=f9cd7ada42a79a0ce552ec597f230bc7bf9a5702'/>
<id>urn:sha1:f9cd7ada42a79a0ce552ec597f230bc7bf9a5702</id>
<content type='text'>
Replace the UAPI text protocol-based wireguard configuration with
wireguard-go's new direct callback API (SetPeerLookupFunc,
SetPeerByIPPacketFunc, RemoveMatchingPeers, SetPrivateKey).

Instead of computing a trimmed wireguard config ahead of time upon
control plane updates and pushing it via UAPI, install callbacks so
wireguard-go creates peers on demand when packets arrive. This removes
all the LazyWG trimming machinery: idle peer tracking, activity maps,
noteRecvActivity callbacks, the KeepFullWGConfig control knob, and the
ts_omit_lazywg build tag.

For incoming packets, PeerLookupFunc answers wireguard-go's questions
about unknown public keys by looking up the peer in the full config.
For outgoing packets, PeerByIPPacketFunc (installed from
LocalBackend.lookupPeerByIP) maps destination IPs to node public keys
using the existing nodeByAddr index.

Updates tailscale/corp#12345

Change-Id: I4cba80979ac49a1231d00a01fdba5f0c2af95dd8
Signed-off-by: Brad Fitzpatrick &lt;bradfitz@tailscale.com&gt;
</content>
</entry>
<entry>
<title>wgengine/magicsock: replace peers slice with peersByID map; add Upsert/RemovePeer</title>
<updated>2026-04-22T22:07:11Z</updated>
<author>
<name>Brad Fitzpatrick</name>
<email>bradfitz@tailscale.com</email>
</author>
<published>2026-04-21T19:19:35Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=311dd3839da3b41c515eec87d3dc040861e6dea6'/>
<id>urn:sha1:311dd3839da3b41c515eec87d3dc040861e6dea6</id>
<content type='text'>
Replace Conn.peers (sorted views.Slice) with peersByID, a
map[tailcfg.NodeID]tailcfg.NodeView. The only caller that needed
the sorted slice (the disco message receive path's binary search)
becomes a single map lookup. Drop nodesEqual.

Add Conn.UpsertPeer / Conn.RemovePeer for O(1) single-peer endpoint
work. RemovePeer also performs a targeted single-disco-key cleanup
(previously that scan was O(discoInfo)).

Extract the shared per-peer upsert body as upsertPeerLocked; still
used by SetNetworkMap's bulk path. SetNetworkMap is documented as
the bulk / initial / self-change path; UpsertPeer and RemovePeer
are preferred for single-peer changes.

Make the relay server set update O(1) per peer: add serverUpsertCh
/ serverRemoveCh to relayManager with matching run-loop handlers.
UpsertPeer / RemovePeer evaluate the per-peer relay predicate
locally and dispatch upsert or remove. The full-rebuild
updateRelayServersSet stays for the initial netmap, filter
changes, and fallback.

Move the hasPeerRelayServers atomic from Conn onto relayManager,
next to the serversByNodeKey map it summarizes. The run loop is
now the single writer and needs no back-pointer to Conn;
endpoint's two hot-path readers take one extra hop to
de.c.relayManager.hasPeerRelayServers but the cost is the same
atomic load.

No callers use UpsertPeer/RemovePeer yet; a subsequent change will
plumb per-peer add/remove through the incremental map update path.

Updates #12542

Change-Id: If6a3442fe29ccbd77890ea61b754a4d1ad6ef225
Signed-off-by: Brad Fitzpatrick &lt;bradfitz@tailscale.com&gt;
</content>
</entry>
<entry>
<title>magicsock: invalidate endpoint on trust timeout (#19415)</title>
<updated>2026-04-16T02:22:07Z</updated>
<author>
<name>Alex Valiushko</name>
<email>alexvaliushko@tailscale.com</email>
</author>
<published>2026-04-16T02:22:07Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=d3ba1480f5c23def55578f9cc086a0d2c6b9a1a9'/>
<id>urn:sha1:d3ba1480f5c23def55578f9cc086a0d2c6b9a1a9</id>
<content type='text'>
Endpoint's best address was cleared on trustBestAddrUntil expiry
only if it was a udprelay connection. This generalizes invalidation
to also cover direct UDP.

Trust deadline is checked in two cases:

On disco ping timeout from the endpoint's best address.
Traffic goes DERP-only, heartbeats to the old address stop.
The discovery pings are still in flight, handled by the following.

On disco ping success from an alternative. BestAddr switches to the
working path, trust refreshed, eager discovery stops. The still
in flight pongs are handled by betterAddr().

Updates #19407


Change-Id: Ic41ed18edb4a6e4350a2d49271ba01566a6a6964

Signed-off-by: Alex Valiushko &lt;alexvaliushko@tailscale.com&gt;</content>
</entry>
<entry>
<title>wgengine/magicsock: send out disco keys over TSMP periodically (#19212)</title>
<updated>2026-04-01T21:20:03Z</updated>
<author>
<name>Claus Lensbøl</name>
<email>claus@tailscale.com</email>
</author>
<published>2026-04-01T21:20:03Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=c76113ac754d64e7cf5fec475e3613d24f7ac28f'/>
<id>urn:sha1:c76113ac754d64e7cf5fec475e3613d24f7ac28f</id>
<content type='text'>
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 &lt;claus@tailscale.com&gt;</content>
</entry>
<entry>
<title>wgengine/magicsock,control/controlclient: do not overwrite discokey with old key (#18606)</title>
<updated>2026-03-20T12:56:27Z</updated>
<author>
<name>Claus Lensbøl</name>
<email>claus@tailscale.com</email>
</author>
<published>2026-03-20T12:56:27Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=85bb5f84a5a31841e3f27d3af952701220a2394f'/>
<id>urn:sha1:85bb5f84a5a31841e3f27d3af952701220a2394f</id>
<content type='text'>
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 &lt;claus@tailscale.com&gt;</content>
</entry>
<entry>
<title>all: fix typos in comments</title>
<updated>2026-03-05T21:52:01Z</updated>
<author>
<name>Brad Fitzpatrick</name>
<email>bradfitz@tailscale.com</email>
</author>
<published>2026-03-05T21:41:12Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=2810f0c6f192775ea89da79f5182cf513516250c'/>
<id>urn:sha1:2810f0c6f192775ea89da79f5182cf513516250c</id>
<content type='text'>
Fix its/it's, who's/whose, wether/whether, missing apostrophes
in contractions, and other misspellings across the codebase.

Updates #cleanup

Change-Id: I20453b81a7aceaa14ea2a551abba08a2e7f0a1d8
Signed-off-by: Brad Fitzpatrick &lt;bradfitz@tailscale.com&gt;
</content>
</entry>
<entry>
<title>all: remove AUTHORS file and references to it</title>
<updated>2026-01-23T23:49:45Z</updated>
<author>
<name>Will Norris</name>
<email>will@tailscale.com</email>
</author>
<published>2026-01-23T21:21:57Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=3ec5be3f510f74738179c1023468343a62a7e00f'/>
<id>urn:sha1:3ec5be3f510f74738179c1023468343a62a7e00f</id>
<content type='text'>
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:

&gt; Adding contributors to the AUTHORS file is entirely within the
&gt; 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 &amp; 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 &amp;\) AUTHORS/\1 contributors/g'

Updates #cleanup

Change-Id: Ia101a4a3005adb9118051b3416f5a64a4a45987d
Signed-off-by: Will Norris &lt;will@tailscale.com&gt;
</content>
</entry>
<entry>
<title>wgengine: send disco key via TSMP on first contact (#18215)</title>
<updated>2026-01-22T19:50:24Z</updated>
<author>
<name>Claus Lensbøl</name>
<email>claus@tailscale.com</email>
</author>
<published>2026-01-22T19:50:24Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=151644f647d9388bb4cb1ae1c4c155b8d8de4cab'/>
<id>urn:sha1:151644f647d9388bb4cb1ae1c4c155b8d8de4cab</id>
<content type='text'>
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 &lt;claus@tailscale.com&gt;</content>
</entry>
<entry>
<title>types/key,wgengine/magicsock,control/controlclient,ipn: add debug disco key rotation</title>
<updated>2025-11-18T20:16:15Z</updated>
<author>
<name>James Tucker</name>
<email>james@tailscale.com</email>
</author>
<published>2025-11-04T00:41:37Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=c09c95ef67d5fe9ff127cf2102f189e47e41b119'/>
<id>urn:sha1:c09c95ef67d5fe9ff127cf2102f189e47e41b119</id>
<content type='text'>
Adds the ability to rotate discovery keys on running clients, needed for
testing upcoming disco key distribution changes.

Introduces key.DiscoKey, an atomic container for a disco private key,
public key, and the public key's ShortString, replacing the prior
separate atomic fields.

magicsock.Conn has a new RotateDiscoKey method, and access to this is
provided via localapi and a CLI debug command.

Note that this implementation is primarily for testing as it stands, and
regular use should likely introduce an additional mechanism that allows
the old key to be used for some time, to provide a seamless key rotation
rather than one that invalidates all sessions.

Updates tailscale/corp#34037

Signed-off-by: James Tucker &lt;james@tailscale.com&gt;
</content>
</entry>
<entry>
<title>syncs: add Mutex/RWMutex alias/wrappers for future mutex debugging</title>
<updated>2025-11-17T03:13:59Z</updated>
<author>
<name>Brad Fitzpatrick</name>
<email>bradfitz@tailscale.com</email>
</author>
<published>2025-11-15T17:40:57Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=99b06eac49ba1cdc1f72409b957f526b25d62622'/>
<id>urn:sha1:99b06eac49ba1cdc1f72409b957f526b25d62622</id>
<content type='text'>
Updates #17852

Change-Id: I477340fb8e40686870e981ade11cd61597c34a20
Signed-off-by: Brad Fitzpatrick &lt;bradfitz@tailscale.com&gt;
</content>
</entry>
</feed>
