summaryrefslogtreecommitdiffhomepage
path: root/ipn/ipnext
AgeCommit message (Collapse)AuthorFilesLines
2026-03-25feature/conn25,ipn/ipnext,ipn/ipnlocal: add ExtraRouterConfigRoutes hookFran Bull1-0/+12
conn25 needs to add routes to the operating system to direct handling of the addresses in the magic IP range to the tailscale0 TUN and tailscaled. The way we do this for exit nodes and VIP services is that we add routes to the Routes field of router.Config, and then the config is passed to the WireGuard engine Reconfig. conn25 is implemented as an ipnext.Extension and so this commit adds a hook to ipnext.Hooks to allow any extension to provide routes to the config. The hook if provided is called in routerConfigLocked, similarly to exit nodes and VIP services. Fixes tailscale/corp#38123 Signed-off-by: Fran Bull <fran@tailscale.com>
2026-03-20ipn/{ipnext,ipnlocal}: expose authReconfig in ipnext.Host as AuthReconfigAsyncMichael Ben-Ami1-0/+10
Also implement a limit of one on the number of goroutines that can be waiting to do a reconfig via AuthReconfig, to prevent extensions from calling too fast and taxing resources. Even with the protection, the new method should only be used in experimental or proof-of-concept contexts. The current intended use is for an extension to be able force a reconfiguration of WireGuard, and have the reconfiguration call back into the extension for extra Allowed IPs. If in the future if WireGuard is able to reconfigure individual peers more dynamically, an extension might be able to hook into that process, and this method on ipnext.Host may be deprecated. Fixes tailscale/corp#38120 Updates tailscale/corp#38124 Updates tailscale/corp#38125 Signed-off-by: Michael Ben-Ami <mzb@tailscale.com>
2026-03-06ipnext,ipnlocal: add ExtraWireGuardAllowedIPs hookMichael Ben-Ami1-0/+26
This hook addition is motivated by the Connectors 2025 work, in which NATed "Transit IPs" are used to route interesting traffic to the appropriate peer, without advertising the actual real IPs. It overlaps with #17858, and specifically with the WIP PR #17861. If that work completes, this hook may be replaced by other ones that fit the new WireGuard configuration paradigm. Fixes tailscale/corp#37146 Signed-off-by: Michael Ben-Ami <mzb@tailscale.com>
2026-02-24ipnext,ipnlocal,wgengine/filter: add extension hooks for custom filter matchersMichael Ben-Ami1-0/+34
Add PacketMatch hooks to the packet filter, allowing extensions to customize filtering decisions: - IngressAllowHooks: checked in RunIn after pre() but before the standard runIn4/runIn6 match rules. Hooks can accept packets to destinations outside the local IP set. First match wins; the returned why string is used for logging. - LinkLocalAllowHooks: checked inside pre() for both ingress and egress, providing exceptions to the default policy of dropping link-local unicast packets. First match wins. The GCP DNS address (169.254.169.254) is always allowed regardless of hooks. PacketMatch returns (match bool, why string) to provide a log reason consistent with the existing filter functions. Hooks are registered via the new FilterHooks struct in ipnext.Hooks and wired through to filter.Filter in LocalBackend.updateFilterLocked. Fixes tailscale/corp#35989 Fixes tailscale/corp#37207 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Michael Ben-Ami <mzb@tailscale.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>
2025-11-13ipn/ipnlocal: remove all the weird locking (LockedOnEntry, UnlockEarly, etc)Brad Fitzpatrick1-1/+2
Fixes #11649 Updates #16369 Co-authored-by: James Sanderson <jsanderson@tailscale.com> Change-Id: I63eaa18fe870ddf81d84b949efac4d1b44c3db86 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-09-25feature/portlist: pull portlist service porting into extension, use eventbusBrad Fitzpatrick1-0/+9
And yay: tsnet (and thus k8s-operator etc) no longer depends on portlist! And LocalBackend is smaller. Removes 50 KB from the minimal binary. Updates #12614 Change-Id: Iee04057053dc39305303e8bd1d9599db8368d926 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-05-19ipn/ipnlocal: make GetExt work earlier, before extension initBrad Fitzpatrick1-1/+1
Taildrop wasn't working on iOS since #15971 because GetExt didn't work until after init, but that PR moved Init until after Start. This makes GetExt work before LocalBackend.Start (ExtensionHost.Init). Updates #15812 Change-Id: I6e87257cd97a20f86083a746d39df223e5b6791b Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-05-14feature/taildrop,ipn/ipn{ext,local}: initialize taildrop for initial profileNick Khyl1-1/+5
Currently, LocalBackend/ExtensionHost doesn't invoke the profile change callback for the initial profile. Since the initial profile may vary depending on loaded extensions and applied policy settings, it can't be reliably determined until all extensions are initialized. Additionally, some extensions may asynchronously trigger a switch to the "best" profile (based on system state and policy settings) during initialization. We intended to address these issues as part of the ongoing profileManager/LocalBackend refactoring, but the changes didn't land in time for the v1.84 release and the Taildrop refactoring. In this PR, we update the Taildrop extension to retrieve the current profile at initialization time and handle it as a profile change. We also defer extension initialization until LocalBackend has started, since the Taildrop extension already relies on this behavior (e.g., it requires clients to call SetDirectFileRoot before Init). Fixes #15970 Updates #15812 Updates tailscale/corp#28449 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-05-06feature/taildrop: move rest of Taildrop out of LocalBackendBrad Fitzpatrick1-1/+48
Updates #12614 Change-Id: If451dec1d796f6a4216fe485975c87f0c62a53e5 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Co-authored-by: Nick Khyl <nickk@tailscale.com>
2025-04-25types/mapx, ipn/ipnext: add ordered map, akin to set.SliceBrad Fitzpatrick1-17/+10
We had an ordered set type (set.Slice) already but we occasionally want to do the same thing with a map, preserving the order things were added, so add that too, as mapsx.OrderedMap[K, V], and then use in ipnext. Updates #12614 Change-Id: I85e6f5e11035571a28316441075e952aef9a0863 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-04-25ipn/ipnext: remove some interface indirection to add hooksBrad Fitzpatrick1-36/+37
Now that 25c4dc5fd70 removed unregistering hooks and made them into slices, just expose the slices and remove the setter funcs. This removes boilerplate ceremony around adding new hooks. This does export the hooks and make them mutable at runtime in theory, but that'd be a data race. If we really wanted to lock it down in the future we could make the feature.Hooks slice type be an opaque struct with an All() iterator and a "frozen" bool and we could freeze all the hooks after init. But that doesn't seem worth it. This means that hook registration is also now all in one place, rather than being mixed into ProfilesService vs ipnext.Host vs FooService vs BarService. I view that as a feature. When we have a ton of hooks and the list is long, then we can rearrange the fields in the Hooks struct as needed, or make sub-structs, or big comments. Updates #12614 Change-Id: I05ce5baa45a61e79c04591c2043c05f3288d8587 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-04-24ipn/{ipnext,ipnlocal}: add a SafeBackend interfaceBrad Fitzpatrick1-5/+19
Updates #12614 Change-Id: I197e673666e86ea74c19e3935ed71aec269b6c94 Co-authored-by: Nick Khyl <nickk@tailscale.com> Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-04-24ipn/ipnext: remove support for unregistering extensionBrad Fitzpatrick1-12/+20
Updates #12614 Change-Id: I893e3ea74831deaa6f88e31bba2d95dc017e0470 Co-authored-by: Nick Khyl <nickk@tailscale.com> Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-04-15ipn/{auditlog,ipnext,ipnlocal}: convert the profile-change callback to a ↵Nick Khyl1-16/+47
profile-state-change callback In this PR, we enable extensions to track changes in the current prefs. These changes can result from a profile switch or from the user or system modifying the current profile’s prefs. Since some extensions may want to distinguish between the two events, while others may treat them similarly, we rename the existing profile-change callback to become a profile-state-change callback and invoke it whenever the current profile or its preferences change. Extensions can still use the sameNode parameter to distinguish between situations where the profile information, including its preferences, has been updated but still represents the same tailnet node, and situations where a switch to a different profile has been made. Having dedicated prefs-change callbacks is being considered, but currently seems redundant. A single profile-state-change callback is easier to maintain. We’ll revisit the idea of adding a separate callback as we progress on extracting existing features from LocalBackend, but the conversion to a profile-state-change callback is intended to be permanent. Finally, we let extensions retrieve the current prefs or profile state (profile info + prefs) at any time using the new CurrentProfileState and CurrentPrefs methods. We also simplify the NewControlClientCallback signature to exclude profile prefs. It’s optional, and extensions can retrieve the current prefs themselves if needed. Updates #12614 Updates tailscale/corp#27645 Updates tailscale/corp#26435 Updates tailscale/corp#27502 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-04-11ipn/ipn{ext,local}: allow extension lookup by name or typeNick Khyl1-0/+19
In this PR, we add two methods to facilitate extension lookup by both extensions, and non-extensions (e.g., PeerAPI or LocalAPI handlers): - FindExtensionByName returns an extension with the specified name. It can then be type asserted to a given type. - FindMatchingExtension is like errors.As, but for extensions. It returns the first extension that matches the target type (either a specific extension or an interface). Updates tailscale/corp#27645 Updates tailscale/corp#27502 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-04-11cmd/tailscaled,ipn/{auditlog,desktop,ipnext,ipnlocal},tsd: extract ↵Nick Khyl1-0/+284
LocalBackend extension interfaces and implementation In this PR, we refactor the LocalBackend extension system, moving from direct callbacks to a more organized extension host model. Specifically, we: - Extract interface and callback types used by packages extending LocalBackend functionality into a new ipn/ipnext package. - Define ipnext.Host as a new interface that bridges extensions with LocalBackend. It enables extensions to register callbacks and interact with LocalBackend in a concurrency-safe, well-defined, and controlled way. - Move existing callback registration and invocation code from ipnlocal.LocalBackend into a new type called ipnlocal.ExtensionHost, implementing ipnext.Host. - Improve docs for existing types and methods while adding docs for the new interfaces. - Add test coverage for both the extracted and the new code. - Remove ipn/desktop.SessionManager from tsd.System since ipn/desktop is now self-contained. - Update existing extensions (e.g., ipn/auditlog and ipn/desktop) to use the new interfaces where appropriate. We're not introducing new callback and hook types (e.g., for ipn.Prefs changes) just yet, nor are we enhancing current callbacks, such as by improving conflict resolution when more than one extension tries to influence profile selection via a background profile resolver. These further improvements will be submitted separately. Updates #12614 Updates tailscale/corp#27645 Updates tailscale/corp#26435 Updates tailscale/corp#18342 Signed-off-by: Nick Khyl <nickk@tailscale.com>