feature/featuretags, all: add build features, use existing ones in more places

Saves 270 KB.

Updates #12614

Change-Id: I4c3fe06d32c49edb3a4bb0758a8617d83f291cf5
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/17392/head
Brad Fitzpatrick 2 months ago committed by Brad Fitzpatrick
parent aa5b2ce83b
commit c45f8813b4

@ -112,7 +112,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
github.com/tailscale/goupnp/soap from github.com/tailscale/goupnp+ github.com/tailscale/goupnp/soap from github.com/tailscale/goupnp+
github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp
github.com/tailscale/hujson from tailscale.com/ipn/conffile+ github.com/tailscale/hujson from tailscale.com/ipn/conffile+
github.com/tailscale/peercred from tailscale.com/ipn/ipnauth LD github.com/tailscale/peercred from tailscale.com/ipn/ipnauth
github.com/tailscale/web-client-prebuilt from tailscale.com/client/web github.com/tailscale/web-client-prebuilt from tailscale.com/client/web
💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+ 💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+
W 💣 github.com/tailscale/wireguard-go/conn/winrio from github.com/tailscale/wireguard-go/conn W 💣 github.com/tailscale/wireguard-go/conn/winrio from github.com/tailscale/wireguard-go/conn

@ -22,9 +22,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
github.com/mdlayher/genetlink from tailscale.com/net/tstun github.com/mdlayher/genetlink from tailscale.com/net/tstun
💣 github.com/mdlayher/netlink from github.com/jsimonetti/rtnetlink+ 💣 github.com/mdlayher/netlink from github.com/jsimonetti/rtnetlink+
💣 github.com/mdlayher/netlink/nlenc from github.com/jsimonetti/rtnetlink+ 💣 github.com/mdlayher/netlink/nlenc from github.com/jsimonetti/rtnetlink+
💣 github.com/mdlayher/socket from github.com/mdlayher/netlink+ 💣 github.com/mdlayher/socket from github.com/mdlayher/netlink
💣 github.com/safchain/ethtool from tailscale.com/net/netkernelconf 💣 github.com/safchain/ethtool from tailscale.com/net/netkernelconf
github.com/tailscale/peercred from tailscale.com/ipn/ipnauth
💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+ 💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+
💣 github.com/tailscale/wireguard-go/device from tailscale.com/net/tstun+ 💣 github.com/tailscale/wireguard-go/device from tailscale.com/net/tstun+
github.com/tailscale/wireguard-go/ipc from github.com/tailscale/wireguard-go/device github.com/tailscale/wireguard-go/ipc from github.com/tailscale/wireguard-go/device
@ -221,10 +220,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
golang.org/x/net/internal/httpcommon from golang.org/x/net/http2 golang.org/x/net/internal/httpcommon from golang.org/x/net/http2
golang.org/x/net/internal/iana from golang.org/x/net/icmp+ golang.org/x/net/internal/iana from golang.org/x/net/icmp+
golang.org/x/net/internal/socket from golang.org/x/net/icmp+ golang.org/x/net/internal/socket from golang.org/x/net/icmp+
golang.org/x/net/internal/socks from golang.org/x/net/proxy
golang.org/x/net/ipv4 from github.com/tailscale/wireguard-go/conn+ golang.org/x/net/ipv4 from github.com/tailscale/wireguard-go/conn+
golang.org/x/net/ipv6 from github.com/tailscale/wireguard-go/conn+ golang.org/x/net/ipv6 from github.com/tailscale/wireguard-go/conn+
golang.org/x/net/proxy from tailscale.com/net/netns
golang.org/x/sync/errgroup from github.com/mdlayher/socket+ golang.org/x/sync/errgroup from github.com/mdlayher/socket+
golang.org/x/sys/cpu from github.com/tailscale/wireguard-go/tun+ golang.org/x/sys/cpu from github.com/tailscale/wireguard-go/tun+
golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+ golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+

@ -28,7 +28,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
github.com/mdlayher/genetlink from tailscale.com/net/tstun github.com/mdlayher/genetlink from tailscale.com/net/tstun
💣 github.com/mdlayher/netlink from github.com/jsimonetti/rtnetlink+ 💣 github.com/mdlayher/netlink from github.com/jsimonetti/rtnetlink+
💣 github.com/mdlayher/netlink/nlenc from github.com/jsimonetti/rtnetlink+ 💣 github.com/mdlayher/netlink/nlenc from github.com/jsimonetti/rtnetlink+
💣 github.com/mdlayher/socket from github.com/mdlayher/netlink+ 💣 github.com/mdlayher/socket from github.com/mdlayher/netlink
github.com/peterbourgon/ff/v3 from github.com/peterbourgon/ff/v3/ffcli+ github.com/peterbourgon/ff/v3 from github.com/peterbourgon/ff/v3/ffcli+
github.com/peterbourgon/ff/v3/ffcli from tailscale.com/cmd/tailscale/cli+ github.com/peterbourgon/ff/v3/ffcli from tailscale.com/cmd/tailscale/cli+
github.com/peterbourgon/ff/v3/internal from github.com/peterbourgon/ff/v3 github.com/peterbourgon/ff/v3/internal from github.com/peterbourgon/ff/v3
@ -36,7 +36,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
github.com/skip2/go-qrcode from tailscale.com/cmd/tailscale/cli github.com/skip2/go-qrcode from tailscale.com/cmd/tailscale/cli
github.com/skip2/go-qrcode/bitset from github.com/skip2/go-qrcode+ github.com/skip2/go-qrcode/bitset from github.com/skip2/go-qrcode+
github.com/skip2/go-qrcode/reedsolomon from github.com/skip2/go-qrcode github.com/skip2/go-qrcode/reedsolomon from github.com/skip2/go-qrcode
github.com/tailscale/peercred from tailscale.com/ipn/ipnauth
💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+ 💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+
💣 github.com/tailscale/wireguard-go/device from tailscale.com/net/tstun+ 💣 github.com/tailscale/wireguard-go/device from tailscale.com/net/tstun+
github.com/tailscale/wireguard-go/ipc from github.com/tailscale/wireguard-go/device github.com/tailscale/wireguard-go/ipc from github.com/tailscale/wireguard-go/device
@ -248,10 +247,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
golang.org/x/net/internal/httpcommon from golang.org/x/net/http2 golang.org/x/net/internal/httpcommon from golang.org/x/net/http2
golang.org/x/net/internal/iana from golang.org/x/net/icmp+ golang.org/x/net/internal/iana from golang.org/x/net/icmp+
golang.org/x/net/internal/socket from golang.org/x/net/icmp+ golang.org/x/net/internal/socket from golang.org/x/net/icmp+
golang.org/x/net/internal/socks from golang.org/x/net/proxy
golang.org/x/net/ipv4 from github.com/tailscale/wireguard-go/conn+ golang.org/x/net/ipv4 from github.com/tailscale/wireguard-go/conn+
golang.org/x/net/ipv6 from github.com/tailscale/wireguard-go/conn+ golang.org/x/net/ipv6 from github.com/tailscale/wireguard-go/conn+
golang.org/x/net/proxy from tailscale.com/net/netns
golang.org/x/sync/errgroup from github.com/mdlayher/socket+ golang.org/x/sync/errgroup from github.com/mdlayher/socket+
golang.org/x/sys/cpu from github.com/tailscale/wireguard-go/tun+ golang.org/x/sys/cpu from github.com/tailscale/wireguard-go/tun+
golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+ golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+

@ -174,7 +174,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
github.com/tailscale/hujson from tailscale.com/ipn/conffile github.com/tailscale/hujson from tailscale.com/ipn/conffile
L 💣 github.com/tailscale/netlink from tailscale.com/net/routetable+ L 💣 github.com/tailscale/netlink from tailscale.com/net/routetable+
L 💣 github.com/tailscale/netlink/nl from github.com/tailscale/netlink L 💣 github.com/tailscale/netlink/nl from github.com/tailscale/netlink
github.com/tailscale/peercred from tailscale.com/ipn/ipnauth LD github.com/tailscale/peercred from tailscale.com/ipn/ipnauth
github.com/tailscale/web-client-prebuilt from tailscale.com/client/web github.com/tailscale/web-client-prebuilt from tailscale.com/client/web
W 💣 github.com/tailscale/wf from tailscale.com/wf W 💣 github.com/tailscale/wf from tailscale.com/wf
💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+ 💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+

@ -237,16 +237,22 @@ func minTags() string {
} }
func TestMinTailscaledNoCLI(t *testing.T) { func TestMinTailscaledNoCLI(t *testing.T) {
badSubstrs := []string{
"cbor",
"regexp",
"golang.org/x/net/proxy",
"internal/socks",
"github.com/tailscale/peercred",
}
deptest.DepChecker{ deptest.DepChecker{
GOOS: "linux", GOOS: "linux",
GOARCH: "amd64", GOARCH: "amd64",
Tags: minTags(), Tags: minTags(),
OnDep: func(dep string) { OnDep: func(dep string) {
if strings.Contains(dep, "regexp") { for _, bad := range badSubstrs {
if strings.Contains(dep, bad) {
t.Errorf("unexpected dep: %q", dep) t.Errorf("unexpected dep: %q", dep)
} }
if strings.Contains(dep, "cbor") {
t.Errorf("unexpected dep: %q", dep)
} }
}, },
}.Check(t) }.Check(t)

@ -58,7 +58,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
github.com/tailscale/goupnp/soap from github.com/tailscale/goupnp+ github.com/tailscale/goupnp/soap from github.com/tailscale/goupnp+
github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp
github.com/tailscale/hujson from tailscale.com/ipn/conffile github.com/tailscale/hujson from tailscale.com/ipn/conffile
github.com/tailscale/peercred from tailscale.com/ipn/ipnauth LD github.com/tailscale/peercred from tailscale.com/ipn/ipnauth
github.com/tailscale/web-client-prebuilt from tailscale.com/client/web github.com/tailscale/web-client-prebuilt from tailscale.com/client/web
💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+ 💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+
W 💣 github.com/tailscale/wireguard-go/conn/winrio from github.com/tailscale/wireguard-go/conn W 💣 github.com/tailscale/wireguard-go/conn/winrio from github.com/tailscale/wireguard-go/conn

@ -0,0 +1,13 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by gen.go; DO NOT EDIT.
//go:build ts_omit_bakedroots
package buildfeatures
// HasBakedRoots is whether the binary was built with support for modular feature "Embed CA (LetsEncrypt) x509 roots to use as fallback".
// Specifically, it's whether the binary was NOT built with the "ts_omit_bakedroots" build tag.
// It's a const so it can be used for dead code elimination.
const HasBakedRoots = false

@ -0,0 +1,13 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by gen.go; DO NOT EDIT.
//go:build !ts_omit_bakedroots
package buildfeatures
// HasBakedRoots is whether the binary was built with support for modular feature "Embed CA (LetsEncrypt) x509 roots to use as fallback".
// Specifically, it's whether the binary was NOT built with the "ts_omit_bakedroots" build tag.
// It's a const so it can be used for dead code elimination.
const HasBakedRoots = true

@ -0,0 +1,13 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by gen.go; DO NOT EDIT.
//go:build ts_omit_cloud
package buildfeatures
// HasCloud is whether the binary was built with support for modular feature "detect cloud environment to learn instances IPs and DNS servers".
// Specifically, it's whether the binary was NOT built with the "ts_omit_cloud" build tag.
// It's a const so it can be used for dead code elimination.
const HasCloud = false

@ -0,0 +1,13 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by gen.go; DO NOT EDIT.
//go:build !ts_omit_cloud
package buildfeatures
// HasCloud is whether the binary was built with support for modular feature "detect cloud environment to learn instances IPs and DNS servers".
// Specifically, it's whether the binary was NOT built with the "ts_omit_cloud" build tag.
// It's a const so it can be used for dead code elimination.
const HasCloud = true

@ -0,0 +1,13 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by gen.go; DO NOT EDIT.
//go:build ts_omit_listenrawdisco
package buildfeatures
// HasListenRawDisco is whether the binary was built with support for modular feature "Use raw sockets for more robust disco (NAT traversal) message receiving (Linux only)".
// Specifically, it's whether the binary was NOT built with the "ts_omit_listenrawdisco" build tag.
// It's a const so it can be used for dead code elimination.
const HasListenRawDisco = false

@ -0,0 +1,13 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by gen.go; DO NOT EDIT.
//go:build !ts_omit_listenrawdisco
package buildfeatures
// HasListenRawDisco is whether the binary was built with support for modular feature "Use raw sockets for more robust disco (NAT traversal) message receiving (Linux only)".
// Specifically, it's whether the binary was NOT built with the "ts_omit_listenrawdisco" build tag.
// It's a const so it can be used for dead code elimination.
const HasListenRawDisco = true

@ -0,0 +1,13 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by gen.go; DO NOT EDIT.
//go:build ts_omit_unixsocketidentity
package buildfeatures
// HasUnixSocketIdentity is whether the binary was built with support for modular feature "differentiate between users accessing the LocalAPI over unix sockets (if omitted, all users have full access)".
// Specifically, it's whether the binary was NOT built with the "ts_omit_unixsocketidentity" build tag.
// It's a const so it can be used for dead code elimination.
const HasUnixSocketIdentity = false

@ -0,0 +1,13 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by gen.go; DO NOT EDIT.
//go:build !ts_omit_unixsocketidentity
package buildfeatures
// HasUnixSocketIdentity is whether the binary was built with support for modular feature "differentiate between users accessing the LocalAPI over unix sockets (if omitted, all users have full access)".
// Specifically, it's whether the binary was NOT built with the "ts_omit_unixsocketidentity" build tag.
// It's a const so it can be used for dead code elimination.
const HasUnixSocketIdentity = true

@ -87,41 +87,47 @@ type FeatureMeta struct {
// Features are the known Tailscale features that can be selectively included or // Features are the known Tailscale features that can be selectively included or
// excluded via build tags, and a description of each. // excluded via build tags, and a description of each.
var Features = map[FeatureTag]FeatureMeta{ var Features = map[FeatureTag]FeatureMeta{
"acme": {"ACME", "ACME TLS certificate management", nil}, "acme": {Sym: "ACME", Desc: "ACME TLS certificate management"},
"appconnectors": {"AppConnectors", "App Connectors support", nil}, "appconnectors": {Sym: "AppConnectors", Desc: "App Connectors support"},
"aws": {"AWS", "AWS integration", nil}, "aws": {Sym: "AWS", Desc: "AWS integration"},
"bird": {"Bird", "Bird BGP integration", nil}, "bakedroots": {Sym: "BakedRoots", Desc: "Embed CA (LetsEncrypt) x509 roots to use as fallback"},
"captiveportal": {"CaptivePortal", "Captive portal detection", nil}, "bird": {Sym: "Bird", Desc: "Bird BGP integration"},
"capture": {"Capture", "Packet capture", nil}, "captiveportal": {Sym: "CaptivePortal", Desc: "Captive portal detection"},
"cli": {"CLI", "embed the CLI into the tailscaled binary", nil}, "capture": {Sym: "Capture", Desc: "Packet capture"},
"cliconndiag": {"CLIConnDiag", "CLI connection error diagnostics", nil}, "cloud": {Sym: "Cloud", Desc: "detect cloud environment to learn instances IPs and DNS servers"},
"clientupdate": {"ClientUpdate", "Client auto-update support", nil}, "cli": {Sym: "CLI", Desc: "embed the CLI into the tailscaled binary"},
"completion": {"Completion", "CLI shell completion", nil}, "cliconndiag": {Sym: "CLIConnDiag", Desc: "CLI connection error diagnostics"},
"dbus": {"DBus", "Linux DBus support", nil}, "clientupdate": {Sym: "ClientUpdate", Desc: "Client auto-update support"},
"debug": {"Debug", "various debug support, for things that don't have or need their own more specific feature", nil}, "completion": {Sym: "Completion", Desc: "CLI shell completion"},
"debugeventbus": {"DebugEventBus", "eventbus debug support", nil}, "dbus": {Sym: "DBus", Desc: "Linux DBus support"},
"debug": {Sym: "Debug", Desc: "various debug support, for things that don't have or need their own more specific feature"},
"debugeventbus": {Sym: "DebugEventBus", Desc: "eventbus debug support"},
"debugportmapper": { "debugportmapper": {
Sym: "DebugPortMapper", Sym: "DebugPortMapper",
Desc: "portmapper debug support", Desc: "portmapper debug support",
Deps: []FeatureTag{"portmapper"}, Deps: []FeatureTag{"portmapper"},
}, },
"desktop_sessions": {"DesktopSessions", "Desktop sessions support", nil}, "desktop_sessions": {Sym: "DesktopSessions", Desc: "Desktop sessions support"},
"doctor": {"Doctor", "Diagnose possible issues with Tailscale and its host environment", nil}, "doctor": {Sym: "Doctor", Desc: "Diagnose possible issues with Tailscale and its host environment"},
"drive": {"Drive", "Tailscale Drive (file server) support", nil}, "drive": {Sym: "Drive", Desc: "Tailscale Drive (file server) support"},
"gro": { "gro": {
Sym: "GRO", Sym: "GRO",
Desc: "Generic Receive Offload support (performance)", Desc: "Generic Receive Offload support (performance)",
Deps: []FeatureTag{"netstack"}, Deps: []FeatureTag{"netstack"},
}, },
"hujsonconf": {"HuJSONConf", "HuJSON config file support", nil}, "hujsonconf": {Sym: "HuJSONConf", Desc: "HuJSON config file support"},
"iptables": {"IPTables", "Linux iptables support", nil}, "iptables": {Sym: "IPTables", Desc: "Linux iptables support"},
"kube": {"Kube", "Kubernetes integration", nil}, "kube": {Sym: "Kube", Desc: "Kubernetes integration"},
"linuxdnsfight": {"LinuxDNSFight", "Linux support for detecting DNS fights (inotify watching of /etc/resolv.conf)", nil}, "linuxdnsfight": {Sym: "LinuxDNSFight", Desc: "Linux support for detecting DNS fights (inotify watching of /etc/resolv.conf)"},
"listenrawdisco": {
Sym: "ListenRawDisco",
Desc: "Use raw sockets for more robust disco (NAT traversal) message receiving (Linux only)",
},
"logtail": { "logtail": {
Sym: "LogTail", Sym: "LogTail",
Desc: "upload logs to log.tailscale.com (debug logs for bug reports and also by network flow logs if enabled)", Desc: "upload logs to log.tailscale.com (debug logs for bug reports and also by network flow logs if enabled)",
}, },
"oauthkey": {"OAuthKey", "OAuth secret-to-authkey resolution support", nil}, "oauthkey": {Sym: "OAuthKey", Desc: "OAuth secret-to-authkey resolution support"},
"outboundproxy": { "outboundproxy": {
Sym: "OutboundProxy", Sym: "OutboundProxy",
Desc: "Support running an outbound localhost HTTP/SOCK5 proxy support that sends traffic over Tailscale", Desc: "Support running an outbound localhost HTTP/SOCK5 proxy support that sends traffic over Tailscale",
@ -137,9 +143,9 @@ var Features = map[FeatureTag]FeatureMeta{
// by some other feature are missing, then it's an error by default unless you accept // by some other feature are missing, then it's an error by default unless you accept
// that it's okay to proceed without that meta feature. // that it's okay to proceed without that meta feature.
}, },
"portlist": {"PortList", "Optionally advertise listening service ports", nil}, "portlist": {Sym: "PortList", Desc: "Optionally advertise listening service ports"},
"portmapper": {"PortMapper", "NAT-PMP/PCP/UPnP port mapping support", nil}, "portmapper": {Sym: "PortMapper", Desc: "NAT-PMP/PCP/UPnP port mapping support"},
"posture": {"Posture", "Device posture checking support", nil}, "posture": {Sym: "Posture", Desc: "Device posture checking support"},
"dns": { "dns": {
Sym: "DNS", Sym: "DNS",
Desc: "MagicDNS and system DNS configuration support", Desc: "MagicDNS and system DNS configuration support",
@ -149,13 +155,13 @@ var Features = map[FeatureTag]FeatureMeta{
Desc: "Network flow logging support", Desc: "Network flow logging support",
Deps: []FeatureTag{"logtail"}, Deps: []FeatureTag{"logtail"},
}, },
"netstack": {"Netstack", "gVisor netstack (userspace networking) support", nil}, "netstack": {Sym: "Netstack", Desc: "gVisor netstack (userspace networking) support"},
"networkmanager": { "networkmanager": {
Sym: "NetworkManager", Sym: "NetworkManager",
Desc: "Linux NetworkManager integration", Desc: "Linux NetworkManager integration",
Deps: []FeatureTag{"dbus"}, Deps: []FeatureTag{"dbus"},
}, },
"relayserver": {"RelayServer", "Relay server", nil}, "relayserver": {Sym: "RelayServer", Desc: "Relay server"},
"resolved": { "resolved": {
Sym: "Resolved", Sym: "Resolved",
Desc: "Linux systemd-resolved integration", Desc: "Linux systemd-resolved integration",
@ -179,21 +185,25 @@ var Features = map[FeatureTag]FeatureMeta{
Sym: "Synology", Sym: "Synology",
Desc: "Synology NAS integration (applies to Linux builds only)", Desc: "Synology NAS integration (applies to Linux builds only)",
}, },
"syspolicy": {"SystemPolicy", "System policy configuration (MDM) support", nil}, "syspolicy": {Sym: "SystemPolicy", Desc: "System policy configuration (MDM) support"},
"systray": { "systray": {
Sym: "SysTray", Sym: "SysTray",
Desc: "Linux system tray", Desc: "Linux system tray",
Deps: []FeatureTag{"dbus"}, Deps: []FeatureTag{"dbus"},
}, },
"taildrop": {"Taildrop", "Taildrop (file sending) support", nil}, "taildrop": {Sym: "Taildrop", Desc: "Taildrop (file sending) support"},
"tailnetlock": {"TailnetLock", "Tailnet Lock support", nil}, "tailnetlock": {Sym: "TailnetLock", Desc: "Tailnet Lock support"},
"tap": {"Tap", "Experimental Layer 2 (ethernet) support", nil}, "tap": {Sym: "Tap", Desc: "Experimental Layer 2 (ethernet) support"},
"tpm": {"TPM", "TPM support", nil}, "tpm": {Sym: "TPM", Desc: "TPM support"},
"unixsocketidentity": {
Sym: "UnixSocketIdentity",
Desc: "differentiate between users accessing the LocalAPI over unix sockets (if omitted, all users have full access)",
},
"useproxy": { "useproxy": {
Sym: "UseProxy", Sym: "UseProxy",
Desc: "Support using system proxies as specified by env vars or the system configuration to reach Tailscale servers.", Desc: "Support using system proxies as specified by env vars or the system configuration to reach Tailscale servers.",
}, },
"wakeonlan": {"WakeOnLAN", "Wake-on-LAN support", nil}, "wakeonlan": {Sym: "WakeOnLAN", Desc: "Wake-on-LAN support"},
"webclient": { "webclient": {
Sym: "WebClient", Desc: "Web client support", Sym: "WebClient", Desc: "Web client support",
Deps: []FeatureTag{"serve"}, Deps: []FeatureTag{"serve"},

@ -14,7 +14,6 @@ import (
"runtime" "runtime"
"strconv" "strconv"
"github.com/tailscale/peercred"
"tailscale.com/envknob" "tailscale.com/envknob"
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/safesocket" "tailscale.com/safesocket"
@ -64,7 +63,7 @@ type ConnIdentity struct {
// Fields used when NotWindows: // Fields used when NotWindows:
isUnixSock bool // Conn is a *net.UnixConn isUnixSock bool // Conn is a *net.UnixConn
creds *peercred.Creds // or nil if peercred.Get was not implemented on this OS creds PeerCreds // or nil if peercred.Get was not implemented on this OS
// Used on Windows: // Used on Windows:
// TODO(bradfitz): merge these into the peercreds package and // TODO(bradfitz): merge these into the peercreds package and
@ -99,7 +98,16 @@ func (ci *ConnIdentity) WindowsUserID() ipn.WindowsUserID {
func (ci *ConnIdentity) Pid() int { return ci.pid } func (ci *ConnIdentity) Pid() int { return ci.pid }
func (ci *ConnIdentity) IsUnixSock() bool { return ci.isUnixSock } func (ci *ConnIdentity) IsUnixSock() bool { return ci.isUnixSock }
func (ci *ConnIdentity) Creds() *peercred.Creds { return ci.creds } func (ci *ConnIdentity) Creds() PeerCreds { return ci.creds }
// PeerCreds is the interface for a github.com/tailscale/peercred.Creds,
// if linked into the binary.
//
// (It's not used on some platforms, or if ts_omit_unixsocketidentity is set.)
type PeerCreds interface {
UserID() (uid string, ok bool)
PID() (pid int, ok bool)
}
var metricIssue869Workaround = clientmetric.NewCounter("issue_869_workaround") var metricIssue869Workaround = clientmetric.NewCounter("issue_869_workaround")

@ -0,0 +1,25 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build !windows && ts_omit_unixsocketidentity
package ipnauth
import (
"net"
"tailscale.com/types/logger"
)
// GetConnIdentity extracts the identity information from the connection
// based on the user who owns the other end of the connection.
// and couldn't. The returned connIdentity has NotWindows set to true.
func GetConnIdentity(_ logger.Logf, c net.Conn) (ci *ConnIdentity, err error) {
return &ConnIdentity{conn: c, notWindows: true}, nil
}
// WindowsToken is unsupported when GOOS != windows and always returns
// ErrNotImplemented.
func (ci *ConnIdentity) WindowsToken() (WindowsToken, error) {
return nil, ErrNotImplemented
}

@ -1,7 +1,7 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
//go:build !windows //go:build !windows && !ts_omit_unixsocketidentity
package ipnauth package ipnauth

@ -10,6 +10,7 @@ import (
"net/http" "net/http"
"path" "path"
"reflect" "reflect"
"runtime"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -34,25 +35,33 @@ import (
var c2nHandlers = map[methodAndPath]c2nHandler{ var c2nHandlers = map[methodAndPath]c2nHandler{
// Debug. // Debug.
req("/echo"): handleC2NEcho, req("/echo"): handleC2NEcho,
req("/debug/goroutines"): handleC2NDebugGoroutines, }
req("/debug/prefs"): handleC2NDebugPrefs,
req("/debug/metrics"): handleC2NDebugMetrics,
req("/debug/component-logging"): handleC2NDebugComponentLogging,
req("/debug/logheap"): handleC2NDebugLogHeap,
req("/debug/netmap"): handleC2NDebugNetMap,
// PPROF - We only expose a subset of typical pprof endpoints for security.
req("/debug/pprof/heap"): handleC2NPprof,
req("/debug/pprof/allocs"): handleC2NPprof,
req("POST /logtail/flush"): handleC2NLogtailFlush, func init() {
req("POST /sockstats"): handleC2NSockStats, if buildfeatures.HasSSH {
RegisterC2N("/ssh/usernames", handleC2NSSHUsernames)
}
if buildfeatures.HasLogTail {
RegisterC2N("POST /logtail/flush", handleC2NLogtailFlush)
}
if buildfeatures.HasDebug {
RegisterC2N("POST /sockstats", handleC2NSockStats)
// SSH // pprof:
req("/ssh/usernames"): handleC2NSSHUsernames, // we only expose a subset of typical pprof endpoints for security.
RegisterC2N("/debug/pprof/heap", handleC2NPprof)
RegisterC2N("/debug/pprof/allocs", handleC2NPprof)
// Linux netfilter. RegisterC2N("/debug/goroutines", handleC2NDebugGoroutines)
req("POST /netfilter-kind"): handleC2NSetNetfilterKind, RegisterC2N("/debug/prefs", handleC2NDebugPrefs)
RegisterC2N("/debug/metrics", handleC2NDebugMetrics)
RegisterC2N("/debug/component-logging", handleC2NDebugComponentLogging)
RegisterC2N("/debug/logheap", handleC2NDebugLogHeap)
RegisterC2N("/debug/netmap", handleC2NDebugNetMap)
}
if runtime.GOOS == "linux" && buildfeatures.HasOSRouter {
RegisterC2N("POST /netfilter-kind", handleC2NSetNetfilterKind)
}
} }
// RegisterC2N registers a new c2n handler for the given pattern. // RegisterC2N registers a new c2n handler for the given pattern.
@ -265,6 +274,10 @@ func handleC2NPprof(b *LocalBackend, w http.ResponseWriter, r *http.Request) {
} }
func handleC2NSSHUsernames(b *LocalBackend, w http.ResponseWriter, r *http.Request) { func handleC2NSSHUsernames(b *LocalBackend, w http.ResponseWriter, r *http.Request) {
if !buildfeatures.HasSSH {
http.Error(w, feature.ErrUnavailable.Error(), http.StatusNotImplemented)
return
}
var req tailcfg.C2NSSHUsernamesRequest var req tailcfg.C2NSSHUsernamesRequest
if r.Method == "POST" { if r.Method == "POST" {
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { if err := json.NewDecoder(r.Body).Decode(&req); err != nil {

@ -1442,7 +1442,7 @@ func (b *LocalBackend) WhoIs(proto string, ipp netip.AddrPort) (n tailcfg.NodeVi
cn := b.currentNode() cn := b.currentNode()
nid, ok := cn.NodeByAddr(ipp.Addr()) nid, ok := cn.NodeByAddr(ipp.Addr())
if !ok { if !ok && buildfeatures.HasNetstack {
var ip netip.Addr var ip netip.Addr
if ipp.Port() != 0 { if ipp.Port() != 0 {
var protos []string var protos []string
@ -5015,6 +5015,9 @@ func (b *LocalBackend) SetVarRoot(dir string) {
// //
// It should only be called before the LocalBackend is used. // It should only be called before the LocalBackend is used.
func (b *LocalBackend) SetLogFlusher(flushFunc func()) { func (b *LocalBackend) SetLogFlusher(flushFunc func()) {
if !buildfeatures.HasLogTail {
return
}
b.logFlushFunc = flushFunc b.logFlushFunc = flushFunc
} }
@ -5023,7 +5026,7 @@ func (b *LocalBackend) SetLogFlusher(flushFunc func()) {
// //
// TryFlushLogs should not block. // TryFlushLogs should not block.
func (b *LocalBackend) TryFlushLogs() bool { func (b *LocalBackend) TryFlushLogs() bool {
if b.logFlushFunc == nil { if !buildfeatures.HasLogTail || b.logFlushFunc == nil {
return false return false
} }
b.logFlushFunc() b.logFlushFunc()

@ -354,11 +354,12 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return return
} }
} }
if strings.HasPrefix(r.URL.Path, "/dns-query") { if buildfeatures.HasDNS && strings.HasPrefix(r.URL.Path, "/dns-query") {
metricDNSCalls.Add(1) metricDNSCalls.Add(1)
h.handleDNSQuery(w, r) h.handleDNSQuery(w, r)
return return
} }
if buildfeatures.HasDebug {
switch r.URL.Path { switch r.URL.Path {
case "/v0/goroutines": case "/v0/goroutines":
h.handleServeGoroutines(w, r) h.handleServeGoroutines(w, r)
@ -382,6 +383,7 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.handleServeSockStats(w, r) h.handleServeSockStats(w, r)
return return
} }
}
if ph, ok := peerAPIHandlers[r.URL.Path]; ok { if ph, ok := peerAPIHandlers[r.URL.Path]; ok {
ph(h, w, r) ph(h, w, r)
return return

@ -12,6 +12,7 @@ import (
"runtime" "runtime"
"time" "time"
"tailscale.com/feature/buildfeatures"
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/ipn/ipnauth" "tailscale.com/ipn/ipnauth"
"tailscale.com/types/logger" "tailscale.com/types/logger"
@ -237,6 +238,11 @@ func connIsLocalAdmin(logf logger.Logf, ci *ipnauth.ConnIdentity, operatorUID st
// Linux. // Linux.
fallthrough fallthrough
case "linux": case "linux":
if !buildfeatures.HasUnixSocketIdentity {
// Everybody is an admin if support for unix socket identities
// is omitted for the build.
return true
}
uid, ok := ci.Creds().UserID() uid, ok := ci.Creds().UserID()
if !ok { if !ok {
return false return false

@ -10,6 +10,8 @@ import (
"net" "net"
"net/http" "net/http"
"tailscale.com/feature"
"tailscale.com/feature/buildfeatures"
"tailscale.com/logpolicy" "tailscale.com/logpolicy"
) )
@ -23,6 +25,10 @@ import (
// precludes that from working and instead the GUI fails to dial out. // precludes that from working and instead the GUI fails to dial out.
// So, go through tailscaled (with a CONNECT request) instead. // So, go through tailscaled (with a CONNECT request) instead.
func (s *Server) handleProxyConnectConn(w http.ResponseWriter, r *http.Request) { func (s *Server) handleProxyConnectConn(w http.ResponseWriter, r *http.Request) {
if !buildfeatures.HasOutboundProxy {
http.Error(w, feature.ErrUnavailable.Error(), http.StatusNotImplemented)
return
}
ctx := r.Context() ctx := r.Context()
if r.Method != "CONNECT" { if r.Method != "CONNECT" {
panic("[unexpected] miswired") panic("[unexpected] miswired")

@ -15,6 +15,7 @@ import (
"net" "net"
"net/http" "net/http"
"os/user" "os/user"
"runtime"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -24,6 +25,7 @@ import (
"tailscale.com/client/tailscale/apitype" "tailscale.com/client/tailscale/apitype"
"tailscale.com/envknob" "tailscale.com/envknob"
"tailscale.com/feature" "tailscale.com/feature"
"tailscale.com/feature/buildfeatures"
"tailscale.com/ipn/ipnauth" "tailscale.com/ipn/ipnauth"
"tailscale.com/ipn/ipnlocal" "tailscale.com/ipn/ipnlocal"
"tailscale.com/ipn/localapi" "tailscale.com/ipn/localapi"
@ -120,6 +122,10 @@ func (s *Server) awaitBackend(ctx context.Context) (_ *ipnlocal.LocalBackend, ok
// This is primarily for the Windows GUI, because wintun can take awhile to // This is primarily for the Windows GUI, because wintun can take awhile to
// come up. See https://github.com/tailscale/tailscale/issues/6522. // come up. See https://github.com/tailscale/tailscale/issues/6522.
func (s *Server) serveServerStatus(w http.ResponseWriter, r *http.Request) { func (s *Server) serveServerStatus(w http.ResponseWriter, r *http.Request) {
if !buildfeatures.HasDebug && runtime.GOOS != "windows" {
http.Error(w, feature.ErrUnavailable.Error(), http.StatusNotFound)
return
}
ctx := r.Context() ctx := r.Context()
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
@ -382,6 +388,9 @@ func isAllDigit(s string) bool {
// connection. It's intended to give your non-root webserver access // connection. It's intended to give your non-root webserver access
// (www-data, caddy, nginx, etc) to certs. // (www-data, caddy, nginx, etc) to certs.
func (a *actor) CanFetchCerts() bool { func (a *actor) CanFetchCerts() bool {
if !buildfeatures.HasACME {
return false
}
if a.ci.IsUnixSock() && a.ci.Creds() != nil { if a.ci.IsUnixSock() && a.ci.Creds() != nil {
connUID, ok := a.ci.Creds().UserID() connUID, ok := a.ci.Creds().UserID()
if ok && connUID == userIDFromString(envknob.String("TS_PERMIT_CERT_UID")) { if ok && connUID == userIDFromString(envknob.String("TS_PERMIT_CERT_UID")) {
@ -398,6 +407,10 @@ func (a *actor) CanFetchCerts() bool {
// //
// onDone must be called when the HTTP request is done. // onDone must be called when the HTTP request is done.
func (s *Server) addActiveHTTPRequest(req *http.Request, actor ipnauth.Actor) (onDone func(), err error) { func (s *Server) addActiveHTTPRequest(req *http.Request, actor ipnauth.Actor) (onDone func(), err error) {
if runtime.GOOS != "windows" && !buildfeatures.HasUnixSocketIdentity {
return func() {}, nil
}
if actor == nil { if actor == nil {
return nil, errors.New("internal error: nil actor") return nil, errors.New("internal error: nil actor")
} }
@ -538,6 +551,10 @@ func (s *Server) Run(ctx context.Context, ln net.Listener) error {
// Windows and via $DEBUG_LISTENER/debug/ipn when tailscaled's --debug flag // Windows and via $DEBUG_LISTENER/debug/ipn when tailscaled's --debug flag
// is used to run a debug server. // is used to run a debug server.
func (s *Server) ServeHTMLStatus(w http.ResponseWriter, r *http.Request) { func (s *Server) ServeHTMLStatus(w http.ResponseWriter, r *http.Request) {
if !buildfeatures.HasDebug {
http.Error(w, feature.ErrUnavailable.Error(), http.StatusNotFound)
return
}
lb := s.lb.Load() lb := s.lb.Load()
if lb == nil { if lb == nil {
http.Error(w, "no LocalBackend", http.StatusServiceUnavailable) http.Error(w, "no LocalBackend", http.StatusServiceUnavailable)

@ -1,7 +1,7 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
//go:build !ios && !js && !android //go:build !ios && !js && !android && !ts_omit_useproxy
package netns package netns

@ -9,13 +9,19 @@ package blockblame
import ( import (
"crypto/x509" "crypto/x509"
"strings" "strings"
"sync"
"tailscale.com/feature/buildfeatures"
) )
// VerifyCertificate checks if the given certificate c is issued by a firewall manufacturer // VerifyCertificate checks if the given certificate c is issued by a firewall manufacturer
// that is known to block Tailscale connections. It returns true and the Manufacturer of // that is known to block Tailscale connections. It returns true and the Manufacturer of
// the equipment if it is, or false and nil if it is not. // the equipment if it is, or false and nil if it is not.
func VerifyCertificate(c *x509.Certificate) (m *Manufacturer, ok bool) { func VerifyCertificate(c *x509.Certificate) (m *Manufacturer, ok bool) {
for _, m := range Manufacturers { if !buildfeatures.HasDebug {
return nil, false
}
for _, m := range manufacturers() {
if m.match != nil && m.match(c) { if m.match != nil && m.match(c) {
return m, true return m, true
} }
@ -33,7 +39,9 @@ type Manufacturer struct {
match matchFunc match matchFunc
} }
var Manufacturers = []*Manufacturer{ func manufacturers() []*Manufacturer {
manufacturersOnce.Do(func() {
manufacturersList = []*Manufacturer{
{ {
Name: "Aruba Networks", Name: "Aruba Networks",
match: issuerContains("Aruba"), match: issuerContains("Aruba"),
@ -71,8 +79,16 @@ var Manufacturers = []*Manufacturer{
issuerContains("Ubiquiti"), issuerContains("Ubiquiti"),
), ),
}, },
}
})
return manufacturersList
} }
var (
manufacturersOnce sync.Once
manufacturersList []*Manufacturer
)
type matchFunc func(*x509.Certificate) bool type matchFunc func(*x509.Certificate) bool
func issuerContains(s string) matchFunc { func issuerContains(s string) matchFunc {

@ -28,6 +28,7 @@ import (
"tailscale.com/derp/derpconst" "tailscale.com/derp/derpconst"
"tailscale.com/envknob" "tailscale.com/envknob"
"tailscale.com/feature/buildfeatures"
"tailscale.com/health" "tailscale.com/health"
"tailscale.com/hostinfo" "tailscale.com/hostinfo"
"tailscale.com/net/bakedroots" "tailscale.com/net/bakedroots"
@ -36,12 +37,6 @@ import (
var counterFallbackOK int32 // atomic var counterFallbackOK int32 // atomic
// If SSLKEYLOGFILE is set, it's a file to which we write our TLS private keys
// in a way that WireShark can read.
//
// See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
var sslKeyLogFile = os.Getenv("SSLKEYLOGFILE")
var debug = envknob.RegisterBool("TS_DEBUG_TLS_DIAL") var debug = envknob.RegisterBool("TS_DEBUG_TLS_DIAL")
// tlsdialWarningPrinted tracks whether we've printed a warning about a given // tlsdialWarningPrinted tracks whether we've printed a warning about a given
@ -80,7 +75,12 @@ func Config(ht *health.Tracker, base *tls.Config) *tls.Config {
// the real TCP connection) because host is the ultimate hostname, but this // the real TCP connection) because host is the ultimate hostname, but this
// tls.Config is used for both the proxy and the ultimate target. // tls.Config is used for both the proxy and the ultimate target.
if n := sslKeyLogFile; n != "" { if buildfeatures.HasDebug {
// If SSLKEYLOGFILE is set, it's a file to which we write our TLS private keys
// in a way that WireShark can read.
//
// See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
if n := os.Getenv("SSLKEYLOGFILE"); n != "" {
f, err := os.OpenFile(n, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600) f, err := os.OpenFile(n, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -88,6 +88,7 @@ func Config(ht *health.Tracker, base *tls.Config) *tls.Config {
log.Printf("WARNING: writing to SSLKEYLOGFILE %v", n) log.Printf("WARNING: writing to SSLKEYLOGFILE %v", n)
conf.KeyLogWriter = f conf.KeyLogWriter = f
} }
}
if conf.InsecureSkipVerify { if conf.InsecureSkipVerify {
panic("unexpected base.InsecureSkipVerify") panic("unexpected base.InsecureSkipVerify")
@ -164,10 +165,12 @@ func Config(ht *health.Tracker, base *tls.Config) *tls.Config {
if debug() { if debug() {
log.Printf("tlsdial(sys %q): %v", dialedHost, errSys) log.Printf("tlsdial(sys %q): %v", dialedHost, errSys)
} }
if !buildfeatures.HasBakedRoots || (errSys == nil && !debug()) {
return errSys
}
// Always verify with our baked-in Let's Encrypt certificate, // If we have baked-in LetsEncrypt roots and we either failed above, or
// so we can log an informational message. This is useful for // debug logging is enabled, also verify with LetsEncrypt.
// detecting SSL MiTM.
opts.Roots = bakedroots.Get() opts.Roots = bakedroots.Get()
_, bakedErr := cs.PeerCertificates[0].Verify(opts) _, bakedErr := cs.PeerCertificates[0].Verify(opts)
if debug() { if debug() {
@ -239,8 +242,8 @@ func SetConfigExpectedCert(c *tls.Config, certDNSName string) {
if debug() { if debug() {
log.Printf("tlsdial(sys %q/%q): %v", c.ServerName, certDNSName, errSys) log.Printf("tlsdial(sys %q/%q): %v", c.ServerName, certDNSName, errSys)
} }
if errSys == nil { if !buildfeatures.HasBakedRoots || errSys == nil {
return nil return errSys
} }
opts.Roots = bakedroots.Get() opts.Roots = bakedroots.Get()
_, err := certs[0].Verify(opts) _, err := certs[0].Verify(opts)

@ -13,6 +13,7 @@ import (
"time" "time"
"tailscale.com/feature" "tailscale.com/feature"
"tailscale.com/feature/buildfeatures"
) )
type closeable interface { type closeable interface {
@ -108,7 +109,12 @@ func LocalTCPPortAndToken() (port int, token string, err error) {
// PlatformUsesPeerCreds reports whether the current platform uses peer credentials // PlatformUsesPeerCreds reports whether the current platform uses peer credentials
// to authenticate connections. // to authenticate connections.
func PlatformUsesPeerCreds() bool { return GOOSUsesPeerCreds(runtime.GOOS) } func PlatformUsesPeerCreds() bool {
if !buildfeatures.HasUnixSocketIdentity {
return false
}
return GOOSUsesPeerCreds(runtime.GOOS)
}
// GOOSUsesPeerCreds is like PlatformUsesPeerCreds but takes a // GOOSUsesPeerCreds is like PlatformUsesPeerCreds but takes a
// runtime.GOOS value instead of using the current one. // runtime.GOOS value instead of using the current one.

@ -58,7 +58,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
github.com/tailscale/goupnp/soap from github.com/tailscale/goupnp+ github.com/tailscale/goupnp/soap from github.com/tailscale/goupnp+
github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp
LDW github.com/tailscale/hujson from tailscale.com/ipn/conffile LDW github.com/tailscale/hujson from tailscale.com/ipn/conffile
github.com/tailscale/peercred from tailscale.com/ipn/ipnauth LDAI github.com/tailscale/peercred from tailscale.com/ipn/ipnauth
LDW github.com/tailscale/web-client-prebuilt from tailscale.com/client/web LDW github.com/tailscale/web-client-prebuilt from tailscale.com/client/web
💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+ 💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+
W 💣 github.com/tailscale/wireguard-go/conn/winrio from github.com/tailscale/wireguard-go/conn W 💣 github.com/tailscale/wireguard-go/conn/winrio from github.com/tailscale/wireguard-go/conn

@ -18,6 +18,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"tailscale.com/feature/buildfeatures"
"tailscale.com/util/set" "tailscale.com/util/set"
) )
@ -130,6 +131,7 @@ func (m *Metric) Publish() {
metrics[m.name] = m metrics[m.name] = m
sortedDirty = true sortedDirty = true
if buildfeatures.HasLogTail {
if m.f != nil { if m.f != nil {
lastLogVal = append(lastLogVal, scanEntry{f: m.f}) lastLogVal = append(lastLogVal, scanEntry{f: m.f})
} else { } else {
@ -140,6 +142,7 @@ func (m *Metric) Publish() {
valFreeList = valFreeList[1:] valFreeList = valFreeList[1:]
lastLogVal = append(lastLogVal, scanEntry{v: m.v}) lastLogVal = append(lastLogVal, scanEntry{v: m.v})
} }
}
m.regIdx = len(unsorted) m.regIdx = len(unsorted)
unsorted = append(unsorted, m) unsorted = append(unsorted, m)
@ -319,6 +322,9 @@ const (
// - increment a metric: (decrements if negative) // - increment a metric: (decrements if negative)
// 'I' + hex(varint(wireid)) + hex(varint(value)) // 'I' + hex(varint(wireid)) + hex(varint(value))
func EncodeLogTailMetricsDelta() string { func EncodeLogTailMetricsDelta() string {
if !buildfeatures.HasLogTail {
return ""
}
mu.Lock() mu.Lock()
defer mu.Unlock() defer mu.Unlock()

@ -16,6 +16,7 @@ import (
"strings" "strings"
"time" "time"
"tailscale.com/feature/buildfeatures"
"tailscale.com/syncs" "tailscale.com/syncs"
"tailscale.com/types/lazy" "tailscale.com/types/lazy"
) )
@ -51,6 +52,9 @@ const (
// ResolverIP returns the cloud host's recursive DNS server or the // ResolverIP returns the cloud host's recursive DNS server or the
// empty string if not available. // empty string if not available.
func (c Cloud) ResolverIP() string { func (c Cloud) ResolverIP() string {
if !buildfeatures.HasCloud {
return ""
}
switch c { switch c {
case GCP: case GCP:
return GoogleMetadataAndDNSIP return GoogleMetadataAndDNSIP
@ -92,6 +96,9 @@ var cloudAtomic syncs.AtomicValue[Cloud]
// Get returns the current cloud, or the empty string if unknown. // Get returns the current cloud, or the empty string if unknown.
func Get() Cloud { func Get() Cloud {
if !buildfeatures.HasCloud {
return ""
}
if c, ok := cloudAtomic.LoadOk(); ok { if c, ok := cloudAtomic.LoadOk(); ok {
return c return c
} }

@ -17,6 +17,7 @@ import (
"strings" "strings"
"time" "time"
"tailscale.com/feature/buildfeatures"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/util/cloudenv" "tailscale.com/util/cloudenv"
) )
@ -34,6 +35,9 @@ type cloudInfo struct {
} }
func newCloudInfo(logf logger.Logf) *cloudInfo { func newCloudInfo(logf logger.Logf) *cloudInfo {
if !buildfeatures.HasCloud {
return nil
}
tr := &http.Transport{ tr := &http.Transport{
DisableKeepAlives: true, DisableKeepAlives: true,
Dial: (&net.Dialer{ Dial: (&net.Dialer{
@ -53,6 +57,9 @@ func newCloudInfo(logf logger.Logf) *cloudInfo {
// if the tailscaled process is running in a known cloud and there are any such // if the tailscaled process is running in a known cloud and there are any such
// IPs present. // IPs present.
func (ci *cloudInfo) GetPublicIPs(ctx context.Context) ([]netip.Addr, error) { func (ci *cloudInfo) GetPublicIPs(ctx context.Context) ([]netip.Addr, error) {
if !buildfeatures.HasCloud {
return nil, nil
}
switch ci.cloud { switch ci.cloud {
case cloudenv.AWS: case cloudenv.AWS:
ret, err := ci.getAWS(ctx) ret, err := ci.getAWS(ctx)

@ -1,7 +1,7 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
//go:build !linux //go:build !linux || ts_omit_listenrawdisco
package magicsock package magicsock

@ -1,6 +1,8 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
//go:build linux && !ts_omit_listenrawdisco
package magicsock package magicsock
import ( import (

@ -435,7 +435,7 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
} }
e.tundev.PreFilterPacketOutboundToWireGuardEngineIntercept = e.handleLocalPackets e.tundev.PreFilterPacketOutboundToWireGuardEngineIntercept = e.handleLocalPackets
if envknob.BoolDefaultTrue("TS_DEBUG_CONNECT_FAILURES") { if buildfeatures.HasDebug && envknob.BoolDefaultTrue("TS_DEBUG_CONNECT_FAILURES") {
if e.tundev.PreFilterPacketInboundFromWireGuard != nil { if e.tundev.PreFilterPacketInboundFromWireGuard != nil {
return nil, errors.New("unexpected PreFilterIn already set") return nil, errors.New("unexpected PreFilterIn already set")
} }

Loading…
Cancel
Save