This commit is contained in:
2026-02-19 10:07:43 +00:00
parent 007438e372
commit 6e637ecf77
1763 changed files with 60820 additions and 279516 deletions

652
vendor/tailscale.com/tsnet/depaware.txt generated vendored Normal file
View File

@@ -0,0 +1,652 @@
tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
filippo.io/edwards25519 from github.com/hdevalence/ed25519consensus
filippo.io/edwards25519/field from filippo.io/edwards25519
W 💣 github.com/alexbrainman/sspi from github.com/alexbrainman/sspi/internal/common+
W github.com/alexbrainman/sspi/internal/common from github.com/alexbrainman/sspi/negotiate
W 💣 github.com/alexbrainman/sspi/negotiate from tailscale.com/net/tshttpproxy
github.com/aws/aws-sdk-go-v2/aws from github.com/aws/aws-sdk-go-v2/aws/defaults+
github.com/aws/aws-sdk-go-v2/aws/defaults from github.com/aws/aws-sdk-go-v2/service/sso+
github.com/aws/aws-sdk-go-v2/aws/middleware from github.com/aws/aws-sdk-go-v2/aws/retry+
github.com/aws/aws-sdk-go-v2/aws/protocol/query from github.com/aws/aws-sdk-go-v2/service/sts
github.com/aws/aws-sdk-go-v2/aws/protocol/restjson from github.com/aws/aws-sdk-go-v2/service/sso+
github.com/aws/aws-sdk-go-v2/aws/protocol/xml from github.com/aws/aws-sdk-go-v2/service/sts
github.com/aws/aws-sdk-go-v2/aws/ratelimit from github.com/aws/aws-sdk-go-v2/aws/retry
github.com/aws/aws-sdk-go-v2/aws/retry from github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client+
github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4 from github.com/aws/aws-sdk-go-v2/aws/signer/v4
github.com/aws/aws-sdk-go-v2/aws/signer/v4 from github.com/aws/aws-sdk-go-v2/internal/auth/smithy+
github.com/aws/aws-sdk-go-v2/aws/transport/http from github.com/aws/aws-sdk-go-v2/config+
github.com/aws/aws-sdk-go-v2/config from tailscale.com/wif
github.com/aws/aws-sdk-go-v2/credentials from github.com/aws/aws-sdk-go-v2/config
github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds from github.com/aws/aws-sdk-go-v2/config
github.com/aws/aws-sdk-go-v2/credentials/endpointcreds from github.com/aws/aws-sdk-go-v2/config
github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client from github.com/aws/aws-sdk-go-v2/credentials/endpointcreds
github.com/aws/aws-sdk-go-v2/credentials/processcreds from github.com/aws/aws-sdk-go-v2/config
github.com/aws/aws-sdk-go-v2/credentials/ssocreds from github.com/aws/aws-sdk-go-v2/config
github.com/aws/aws-sdk-go-v2/credentials/stscreds from github.com/aws/aws-sdk-go-v2/config
github.com/aws/aws-sdk-go-v2/feature/ec2/imds from github.com/aws/aws-sdk-go-v2/config+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds/internal/config from github.com/aws/aws-sdk-go-v2/feature/ec2/imds
github.com/aws/aws-sdk-go-v2/internal/auth from github.com/aws/aws-sdk-go-v2/aws/signer/v4+
github.com/aws/aws-sdk-go-v2/internal/auth/smithy from github.com/aws/aws-sdk-go-v2/service/sso+
github.com/aws/aws-sdk-go-v2/internal/configsources from github.com/aws/aws-sdk-go-v2/service/sso+
github.com/aws/aws-sdk-go-v2/internal/context from github.com/aws/aws-sdk-go-v2/aws/retry+
github.com/aws/aws-sdk-go-v2/internal/endpoints from github.com/aws/aws-sdk-go-v2/service/sso+
github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn from github.com/aws/aws-sdk-go-v2/service/sso+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 from github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints+
github.com/aws/aws-sdk-go-v2/internal/ini from github.com/aws/aws-sdk-go-v2/config
github.com/aws/aws-sdk-go-v2/internal/middleware from github.com/aws/aws-sdk-go-v2/service/sso+
github.com/aws/aws-sdk-go-v2/internal/rand from github.com/aws/aws-sdk-go-v2/aws+
github.com/aws/aws-sdk-go-v2/internal/sdk from github.com/aws/aws-sdk-go-v2/aws+
github.com/aws/aws-sdk-go-v2/internal/sdkio from github.com/aws/aws-sdk-go-v2/credentials/processcreds
github.com/aws/aws-sdk-go-v2/internal/shareddefaults from github.com/aws/aws-sdk-go-v2/config+
github.com/aws/aws-sdk-go-v2/internal/strings from github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4
github.com/aws/aws-sdk-go-v2/internal/sync/singleflight from github.com/aws/aws-sdk-go-v2/aws
github.com/aws/aws-sdk-go-v2/internal/timeconv from github.com/aws/aws-sdk-go-v2/aws/retry
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding from github.com/aws/aws-sdk-go-v2/service/sts
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url from github.com/aws/aws-sdk-go-v2/service/sts
github.com/aws/aws-sdk-go-v2/service/sso from github.com/aws/aws-sdk-go-v2/config+
github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints from github.com/aws/aws-sdk-go-v2/service/sso
github.com/aws/aws-sdk-go-v2/service/sso/types from github.com/aws/aws-sdk-go-v2/service/sso
github.com/aws/aws-sdk-go-v2/service/ssooidc from github.com/aws/aws-sdk-go-v2/config+
github.com/aws/aws-sdk-go-v2/service/ssooidc/internal/endpoints from github.com/aws/aws-sdk-go-v2/service/ssooidc
github.com/aws/aws-sdk-go-v2/service/ssooidc/types from github.com/aws/aws-sdk-go-v2/service/ssooidc
github.com/aws/aws-sdk-go-v2/service/sts from github.com/aws/aws-sdk-go-v2/config+
github.com/aws/aws-sdk-go-v2/service/sts/internal/endpoints from github.com/aws/aws-sdk-go-v2/service/sts
github.com/aws/aws-sdk-go-v2/service/sts/types from github.com/aws/aws-sdk-go-v2/credentials/stscreds+
github.com/aws/smithy-go from github.com/aws/aws-sdk-go-v2/aws/protocol/restjson+
github.com/aws/smithy-go/auth from github.com/aws/aws-sdk-go-v2/internal/auth+
github.com/aws/smithy-go/auth/bearer from github.com/aws/aws-sdk-go-v2/aws+
github.com/aws/smithy-go/context from github.com/aws/smithy-go/auth/bearer
github.com/aws/smithy-go/document from github.com/aws/aws-sdk-go-v2/service/sso+
github.com/aws/smithy-go/encoding from github.com/aws/smithy-go/encoding/json+
github.com/aws/smithy-go/encoding/httpbinding from github.com/aws/aws-sdk-go-v2/aws/protocol/query+
github.com/aws/smithy-go/encoding/json from github.com/aws/aws-sdk-go-v2/service/ssooidc
github.com/aws/smithy-go/encoding/xml from github.com/aws/aws-sdk-go-v2/service/sts
github.com/aws/smithy-go/endpoints from github.com/aws/aws-sdk-go-v2/service/sso+
github.com/aws/smithy-go/endpoints/private/rulesfn from github.com/aws/aws-sdk-go-v2/service/sts
github.com/aws/smithy-go/internal/sync/singleflight from github.com/aws/smithy-go/auth/bearer
github.com/aws/smithy-go/io from github.com/aws/aws-sdk-go-v2/feature/ec2/imds+
github.com/aws/smithy-go/logging from github.com/aws/aws-sdk-go-v2/aws+
github.com/aws/smithy-go/metrics from github.com/aws/aws-sdk-go-v2/aws/retry+
github.com/aws/smithy-go/middleware from github.com/aws/aws-sdk-go-v2/aws+
github.com/aws/smithy-go/private/requestcompression from github.com/aws/aws-sdk-go-v2/config
github.com/aws/smithy-go/ptr from github.com/aws/aws-sdk-go-v2/aws+
github.com/aws/smithy-go/rand from github.com/aws/aws-sdk-go-v2/aws/middleware
github.com/aws/smithy-go/time from github.com/aws/aws-sdk-go-v2/service/sso+
github.com/aws/smithy-go/tracing from github.com/aws/aws-sdk-go-v2/aws/middleware+
github.com/aws/smithy-go/transport/http from github.com/aws/aws-sdk-go-v2/aws+
github.com/aws/smithy-go/transport/http/internal/io from github.com/aws/smithy-go/transport/http
LDW github.com/coder/websocket from tailscale.com/util/eventbus
LDW github.com/coder/websocket/internal/errd from github.com/coder/websocket
LDW github.com/coder/websocket/internal/util from github.com/coder/websocket
LDW github.com/coder/websocket/internal/xsync from github.com/coder/websocket
github.com/creachadair/msync/trigger from tailscale.com/logtail
W 💣 github.com/dblohm7/wingoes from tailscale.com/net/tshttpproxy+
W 💣 github.com/dblohm7/wingoes/com from tailscale.com/util/osdiag+
W 💣 github.com/dblohm7/wingoes/com/automation from tailscale.com/util/osdiag/internal/wsc
W github.com/dblohm7/wingoes/internal from github.com/dblohm7/wingoes/com
W 💣 github.com/dblohm7/wingoes/pe from tailscale.com/util/osdiag+
github.com/fxamacker/cbor/v2 from tailscale.com/tka
github.com/gaissmai/bart from tailscale.com/net/ipset+
github.com/gaissmai/bart/internal/bitset from github.com/gaissmai/bart+
github.com/gaissmai/bart/internal/sparse from github.com/gaissmai/bart
github.com/go-json-experiment/json from tailscale.com/types/opt+
github.com/go-json-experiment/json/internal from github.com/go-json-experiment/json+
github.com/go-json-experiment/json/internal/jsonflags from github.com/go-json-experiment/json+
github.com/go-json-experiment/json/internal/jsonopts from github.com/go-json-experiment/json+
github.com/go-json-experiment/json/internal/jsonwire from github.com/go-json-experiment/json+
github.com/go-json-experiment/json/jsontext from github.com/go-json-experiment/json+
L 💣 github.com/godbus/dbus/v5 from tailscale.com/net/dns
github.com/golang/groupcache/lru from tailscale.com/net/dnscache
github.com/google/btree from gvisor.dev/gvisor/pkg/tcpip/header+
DI github.com/google/uuid from github.com/prometheus-community/pro-bing
github.com/hdevalence/ed25519consensus from tailscale.com/tka
github.com/huin/goupnp from github.com/huin/goupnp/dcps/internetgateway2+
github.com/huin/goupnp/dcps/internetgateway2 from tailscale.com/net/portmapper
github.com/huin/goupnp/httpu from github.com/huin/goupnp+
github.com/huin/goupnp/scpd from github.com/huin/goupnp
github.com/huin/goupnp/soap from github.com/huin/goupnp+
github.com/huin/goupnp/ssdp from github.com/huin/goupnp
L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/netmon
L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink
github.com/klauspost/compress from github.com/klauspost/compress/zstd
github.com/klauspost/compress/fse from github.com/klauspost/compress/huff0
github.com/klauspost/compress/huff0 from github.com/klauspost/compress/zstd
github.com/klauspost/compress/internal/cpuinfo from github.com/klauspost/compress/huff0+
💣 github.com/klauspost/compress/internal/le from github.com/klauspost/compress/huff0+
github.com/klauspost/compress/internal/snapref from github.com/klauspost/compress/zstd
github.com/klauspost/compress/zstd from tailscale.com/util/zstdframe
github.com/klauspost/compress/zstd/internal/xxhash from github.com/klauspost/compress/zstd
L 💣 github.com/mdlayher/netlink from github.com/jsimonetti/rtnetlink+
L 💣 github.com/mdlayher/netlink/nlenc from github.com/jsimonetti/rtnetlink+
LA 💣 github.com/mdlayher/socket from github.com/mdlayher/netlink+
LDW 💣 github.com/mitchellh/go-ps from tailscale.com/safesocket
github.com/pires/go-proxyproto from tailscale.com/ipn/ipnlocal
DI github.com/prometheus-community/pro-bing from tailscale.com/wgengine/netstack
L 💣 github.com/safchain/ethtool from tailscale.com/net/netkernelconf
W 💣 github.com/tailscale/certstore from tailscale.com/control/controlclient
W 💣 github.com/tailscale/go-winio from tailscale.com/safesocket
W 💣 github.com/tailscale/go-winio/internal/fs from github.com/tailscale/go-winio
W 💣 github.com/tailscale/go-winio/internal/socket from github.com/tailscale/go-winio
W github.com/tailscale/go-winio/internal/stringbuffer from github.com/tailscale/go-winio/internal/fs
W github.com/tailscale/go-winio/pkg/guid from github.com/tailscale/go-winio+
LDW github.com/tailscale/hujson from tailscale.com/ipn/conffile
LDAI github.com/tailscale/peercred from tailscale.com/ipn/ipnauth
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+
W 💣 github.com/tailscale/wireguard-go/conn/winrio from github.com/tailscale/wireguard-go/conn
💣 github.com/tailscale/wireguard-go/device from tailscale.com/net/tstun+
💣 github.com/tailscale/wireguard-go/ipc from github.com/tailscale/wireguard-go/device
W 💣 github.com/tailscale/wireguard-go/ipc/namedpipe from github.com/tailscale/wireguard-go/ipc
github.com/tailscale/wireguard-go/ratelimiter from github.com/tailscale/wireguard-go/device
github.com/tailscale/wireguard-go/replay from github.com/tailscale/wireguard-go/device
github.com/tailscale/wireguard-go/rwcancel from github.com/tailscale/wireguard-go/device+
github.com/tailscale/wireguard-go/tai64n from github.com/tailscale/wireguard-go/device
💣 github.com/tailscale/wireguard-go/tun from github.com/tailscale/wireguard-go/device+
github.com/x448/float16 from github.com/fxamacker/cbor/v2
💣 go4.org/mem from tailscale.com/client/local+
go4.org/netipx from tailscale.com/ipn/ipnlocal+
W 💣 golang.zx2c4.com/wintun from github.com/tailscale/wireguard-go/tun
W 💣 golang.zx2c4.com/wireguard/windows/tunnel/winipcfg from tailscale.com/net/dns+
gvisor.dev/gvisor/pkg/atomicbitops from gvisor.dev/gvisor/pkg/buffer+
gvisor.dev/gvisor/pkg/bits from gvisor.dev/gvisor/pkg/buffer
💣 gvisor.dev/gvisor/pkg/buffer from gvisor.dev/gvisor/pkg/tcpip+
gvisor.dev/gvisor/pkg/context from gvisor.dev/gvisor/pkg/refs
💣 gvisor.dev/gvisor/pkg/gohacks from gvisor.dev/gvisor/pkg/state/wire+
gvisor.dev/gvisor/pkg/linewriter from gvisor.dev/gvisor/pkg/log
gvisor.dev/gvisor/pkg/log from gvisor.dev/gvisor/pkg/context+
gvisor.dev/gvisor/pkg/rand from gvisor.dev/gvisor/pkg/tcpip+
gvisor.dev/gvisor/pkg/refs from gvisor.dev/gvisor/pkg/buffer+
💣 gvisor.dev/gvisor/pkg/sleep from gvisor.dev/gvisor/pkg/tcpip/transport/tcp
💣 gvisor.dev/gvisor/pkg/state from gvisor.dev/gvisor/pkg/atomicbitops+
gvisor.dev/gvisor/pkg/state/wire from gvisor.dev/gvisor/pkg/state
💣 gvisor.dev/gvisor/pkg/sync from gvisor.dev/gvisor/pkg/atomicbitops+
💣 gvisor.dev/gvisor/pkg/sync/locking from gvisor.dev/gvisor/pkg/tcpip/stack
gvisor.dev/gvisor/pkg/tcpip from gvisor.dev/gvisor/pkg/tcpip/adapters/gonet+
gvisor.dev/gvisor/pkg/tcpip/adapters/gonet from tailscale.com/wgengine/netstack
💣 gvisor.dev/gvisor/pkg/tcpip/checksum from gvisor.dev/gvisor/pkg/buffer+
gvisor.dev/gvisor/pkg/tcpip/hash/jenkins from gvisor.dev/gvisor/pkg/tcpip/stack+
gvisor.dev/gvisor/pkg/tcpip/header from gvisor.dev/gvisor/pkg/tcpip/header/parse+
gvisor.dev/gvisor/pkg/tcpip/header/parse from gvisor.dev/gvisor/pkg/tcpip/network/ipv4+
gvisor.dev/gvisor/pkg/tcpip/internal/tcp from gvisor.dev/gvisor/pkg/tcpip/transport/tcp
gvisor.dev/gvisor/pkg/tcpip/network/hash from gvisor.dev/gvisor/pkg/tcpip/network/ipv4
gvisor.dev/gvisor/pkg/tcpip/network/internal/fragmentation from gvisor.dev/gvisor/pkg/tcpip/network/ipv4+
gvisor.dev/gvisor/pkg/tcpip/network/internal/ip from gvisor.dev/gvisor/pkg/tcpip/network/ipv4+
gvisor.dev/gvisor/pkg/tcpip/network/internal/multicast from gvisor.dev/gvisor/pkg/tcpip/network/ipv4+
gvisor.dev/gvisor/pkg/tcpip/network/ipv4 from tailscale.com/wgengine/netstack
gvisor.dev/gvisor/pkg/tcpip/network/ipv6 from tailscale.com/wgengine/netstack
gvisor.dev/gvisor/pkg/tcpip/ports from gvisor.dev/gvisor/pkg/tcpip/stack+
gvisor.dev/gvisor/pkg/tcpip/seqnum from gvisor.dev/gvisor/pkg/tcpip/header+
💣 gvisor.dev/gvisor/pkg/tcpip/stack from gvisor.dev/gvisor/pkg/tcpip/adapters/gonet+
LDWA gvisor.dev/gvisor/pkg/tcpip/stack/gro from tailscale.com/wgengine/netstack/gro
gvisor.dev/gvisor/pkg/tcpip/transport from gvisor.dev/gvisor/pkg/tcpip/transport/icmp+
gvisor.dev/gvisor/pkg/tcpip/transport/icmp from tailscale.com/wgengine/netstack
gvisor.dev/gvisor/pkg/tcpip/transport/internal/network from gvisor.dev/gvisor/pkg/tcpip/transport/icmp+
gvisor.dev/gvisor/pkg/tcpip/transport/internal/noop from gvisor.dev/gvisor/pkg/tcpip/transport/raw
gvisor.dev/gvisor/pkg/tcpip/transport/packet from gvisor.dev/gvisor/pkg/tcpip/transport/raw
gvisor.dev/gvisor/pkg/tcpip/transport/raw from gvisor.dev/gvisor/pkg/tcpip/transport/icmp+
💣 gvisor.dev/gvisor/pkg/tcpip/transport/tcp from gvisor.dev/gvisor/pkg/tcpip/adapters/gonet+
gvisor.dev/gvisor/pkg/tcpip/transport/tcpconntrack from gvisor.dev/gvisor/pkg/tcpip/stack
gvisor.dev/gvisor/pkg/tcpip/transport/udp from gvisor.dev/gvisor/pkg/tcpip/adapters/gonet+
gvisor.dev/gvisor/pkg/waiter from gvisor.dev/gvisor/pkg/context+
tailscale.com from tailscale.com/version
tailscale.com/appc from tailscale.com/ipn/ipnlocal
💣 tailscale.com/atomicfile from tailscale.com/ipn+
tailscale.com/client/local from tailscale.com/client/web+
tailscale.com/client/tailscale from tailscale.com/internal/client/tailscale
tailscale.com/client/tailscale/apitype from tailscale.com/client/local+
LDW tailscale.com/client/web from tailscale.com/ipn/ipnlocal
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
tailscale.com/control/controlclient from tailscale.com/ipn/ipnext+
tailscale.com/control/controlhttp from tailscale.com/control/ts2021
tailscale.com/control/controlhttp/controlhttpcommon from tailscale.com/control/controlhttp
tailscale.com/control/controlknobs from tailscale.com/control/controlclient+
tailscale.com/control/ts2021 from tailscale.com/control/controlclient
tailscale.com/derp from tailscale.com/derp/derphttp+
tailscale.com/derp/derpconst from tailscale.com/derp/derphttp+
tailscale.com/derp/derphttp from tailscale.com/ipn/localapi+
tailscale.com/disco from tailscale.com/net/tstun+
tailscale.com/drive from tailscale.com/client/local+
tailscale.com/envknob from tailscale.com/client/local+
tailscale.com/envknob/featureknob from tailscale.com/client/web+
tailscale.com/feature from tailscale.com/ipn/ipnext+
tailscale.com/feature/buildfeatures from tailscale.com/wgengine/magicsock+
tailscale.com/feature/c2n from tailscale.com/tsnet
tailscale.com/feature/condlite/expvar from tailscale.com/wgengine/magicsock
tailscale.com/feature/condregister/identityfederation from tailscale.com/tsnet
tailscale.com/feature/condregister/oauthkey from tailscale.com/tsnet
tailscale.com/feature/condregister/portmapper from tailscale.com/tsnet
tailscale.com/feature/condregister/useproxy from tailscale.com/tsnet
tailscale.com/feature/identityfederation from tailscale.com/feature/condregister/identityfederation
tailscale.com/feature/oauthkey from tailscale.com/feature/condregister/oauthkey
tailscale.com/feature/portmapper from tailscale.com/feature/condregister/portmapper
tailscale.com/feature/syspolicy from tailscale.com/logpolicy
tailscale.com/feature/useproxy from tailscale.com/feature/condregister/useproxy
tailscale.com/health from tailscale.com/control/controlclient+
tailscale.com/health/healthmsg from tailscale.com/ipn/ipnlocal+
tailscale.com/hostinfo from tailscale.com/client/web+
tailscale.com/internal/client/tailscale from tailscale.com/tsnet+
tailscale.com/ipn from tailscale.com/client/local+
tailscale.com/ipn/conffile from tailscale.com/ipn/ipnlocal+
💣 tailscale.com/ipn/ipnauth from tailscale.com/ipn/ipnext+
tailscale.com/ipn/ipnext from tailscale.com/ipn/ipnlocal
tailscale.com/ipn/ipnlocal from tailscale.com/ipn/localapi+
tailscale.com/ipn/ipnstate from tailscale.com/client/local+
tailscale.com/ipn/localapi from tailscale.com/tsnet
tailscale.com/ipn/store from tailscale.com/ipn/ipnlocal+
tailscale.com/ipn/store/mem from tailscale.com/ipn/ipnlocal+
tailscale.com/kube/kubetypes from tailscale.com/envknob
LDW tailscale.com/licenses from tailscale.com/client/web
tailscale.com/log/filelogger from tailscale.com/logpolicy
tailscale.com/log/sockstatlog from tailscale.com/ipn/ipnlocal
tailscale.com/logpolicy from tailscale.com/ipn/ipnlocal+
tailscale.com/logtail from tailscale.com/control/controlclient+
tailscale.com/logtail/filch from tailscale.com/log/sockstatlog+
tailscale.com/metrics from tailscale.com/tsweb+
tailscale.com/net/bakedroots from tailscale.com/ipn/ipnlocal+
💣 tailscale.com/net/batching from tailscale.com/wgengine/magicsock
tailscale.com/net/captivedetection from tailscale.com/ipn/ipnlocal+
tailscale.com/net/dns from tailscale.com/ipn/ipnlocal+
tailscale.com/net/dns/publicdns from tailscale.com/net/dns+
tailscale.com/net/dns/resolvconffile from tailscale.com/net/dns+
tailscale.com/net/dns/resolver from tailscale.com/net/dns+
tailscale.com/net/dnscache from tailscale.com/control/controlclient+
tailscale.com/net/dnsfallback from tailscale.com/control/controlclient+
tailscale.com/net/flowtrack from tailscale.com/wgengine+
tailscale.com/net/ipset from tailscale.com/ipn/ipnlocal+
tailscale.com/net/memnet from tailscale.com/tsnet
tailscale.com/net/netaddr from tailscale.com/ipn+
tailscale.com/net/netcheck from tailscale.com/ipn/ipnlocal+
tailscale.com/net/neterror from tailscale.com/net/dns/resolver+
tailscale.com/net/netkernelconf from tailscale.com/ipn/ipnlocal
tailscale.com/net/netknob from tailscale.com/logpolicy+
💣 tailscale.com/net/netmon from tailscale.com/control/controlclient+
💣 tailscale.com/net/netns from tailscale.com/derp/derphttp+
tailscale.com/net/netutil from tailscale.com/client/local+
tailscale.com/net/netx from tailscale.com/control/controlclient+
tailscale.com/net/packet from tailscale.com/ipn/ipnlocal+
tailscale.com/net/packet/checksum from tailscale.com/net/tstun
tailscale.com/net/ping from tailscale.com/net/netcheck+
tailscale.com/net/portmapper from tailscale.com/feature/portmapper
tailscale.com/net/portmapper/portmappertype from tailscale.com/net/netcheck+
tailscale.com/net/proxymux from tailscale.com/tsnet
💣 tailscale.com/net/sockopts from tailscale.com/wgengine/magicsock
tailscale.com/net/socks5 from tailscale.com/tsnet
tailscale.com/net/sockstats from tailscale.com/control/controlclient+
tailscale.com/net/stun from tailscale.com/ipn/localapi+
tailscale.com/net/tlsdial from tailscale.com/control/controlclient+
tailscale.com/net/tlsdial/blockblame from tailscale.com/net/tlsdial
tailscale.com/net/tsaddr from tailscale.com/client/web+
tailscale.com/net/tsdial from tailscale.com/control/controlclient+
💣 tailscale.com/net/tshttpproxy from tailscale.com/feature/useproxy
tailscale.com/net/tstun from tailscale.com/tsd+
tailscale.com/net/udprelay/endpoint from tailscale.com/wgengine/magicsock
tailscale.com/net/udprelay/status from tailscale.com/client/local
tailscale.com/omit from tailscale.com/ipn/conffile
tailscale.com/paths from tailscale.com/client/local+
tailscale.com/proxymap from tailscale.com/tsd+
💣 tailscale.com/safesocket from tailscale.com/client/local+
tailscale.com/syncs from tailscale.com/control/controlhttp+
tailscale.com/tailcfg from tailscale.com/client/local+
tailscale.com/tempfork/acme from tailscale.com/ipn/ipnlocal
tailscale.com/tempfork/heap from tailscale.com/wgengine/magicsock
tailscale.com/tempfork/httprec from tailscale.com/feature/c2n
tailscale.com/tka from tailscale.com/client/local+
tailscale.com/tsconst from tailscale.com/ipn/ipnlocal+
tailscale.com/tsd from tailscale.com/ipn/ipnext+
tailscale.com/tstime from tailscale.com/control/controlclient+
tailscale.com/tstime/mono from tailscale.com/net/tstun+
tailscale.com/tstime/rate from tailscale.com/wgengine/filter
LDW tailscale.com/tsweb from tailscale.com/util/eventbus
tailscale.com/tsweb/varz from tailscale.com/tsweb+
tailscale.com/types/appctype from tailscale.com/ipn/ipnlocal+
tailscale.com/types/bools from tailscale.com/tsnet+
tailscale.com/types/dnstype from tailscale.com/client/local+
tailscale.com/types/empty from tailscale.com/ipn+
tailscale.com/types/ipproto from tailscale.com/ipn+
tailscale.com/types/key from tailscale.com/client/local+
tailscale.com/types/lazy from tailscale.com/hostinfo+
tailscale.com/types/logger from tailscale.com/appc+
tailscale.com/types/logid from tailscale.com/ipn/ipnlocal+
tailscale.com/types/mapx from tailscale.com/ipn/ipnext
tailscale.com/types/netlogfunc from tailscale.com/net/tstun+
tailscale.com/types/netlogtype from tailscale.com/wgengine/netlog
tailscale.com/types/netmap from tailscale.com/control/controlclient+
tailscale.com/types/nettype from tailscale.com/ipn/localapi+
tailscale.com/types/opt from tailscale.com/control/controlknobs+
tailscale.com/types/persist from tailscale.com/control/controlclient+
tailscale.com/types/preftype from tailscale.com/ipn+
tailscale.com/types/ptr from tailscale.com/control/controlclient+
tailscale.com/types/result from tailscale.com/util/lineiter
tailscale.com/types/structs from tailscale.com/control/controlclient+
tailscale.com/types/tkatype from tailscale.com/client/local+
tailscale.com/types/views from tailscale.com/appc+
tailscale.com/util/backoff from tailscale.com/control/controlclient+
tailscale.com/util/checkchange from tailscale.com/ipn/ipnlocal+
tailscale.com/util/cibuild from tailscale.com/health+
tailscale.com/util/clientmetric from tailscale.com/appc+
tailscale.com/util/cloudenv from tailscale.com/hostinfo+
tailscale.com/util/cloudinfo from tailscale.com/wgengine/magicsock
LW tailscale.com/util/cmpver from tailscale.com/net/dns+
tailscale.com/util/ctxkey from tailscale.com/client/tailscale/apitype+
💣 tailscale.com/util/deephash from tailscale.com/util/syspolicy/setting
LA 💣 tailscale.com/util/dirwalk from tailscale.com/metrics
tailscale.com/util/dnsname from tailscale.com/appc+
tailscale.com/util/eventbus from tailscale.com/client/local+
tailscale.com/util/execqueue from tailscale.com/appc+
tailscale.com/util/goroutines from tailscale.com/ipn/ipnlocal
tailscale.com/util/groupmember from tailscale.com/client/web+
💣 tailscale.com/util/hashx from tailscale.com/util/deephash
tailscale.com/util/httpm from tailscale.com/client/web+
tailscale.com/util/lineiter from tailscale.com/hostinfo+
tailscale.com/util/mak from tailscale.com/appc+
tailscale.com/util/must from tailscale.com/logpolicy+
tailscale.com/util/nocasemaps from tailscale.com/types/ipproto
💣 tailscale.com/util/osdiag from tailscale.com/ipn/localapi
W 💣 tailscale.com/util/osdiag/internal/wsc from tailscale.com/util/osdiag
tailscale.com/util/osuser from tailscale.com/ipn/ipnlocal
tailscale.com/util/race from tailscale.com/net/dns/resolver
tailscale.com/util/racebuild from tailscale.com/logpolicy
tailscale.com/util/rands from tailscale.com/ipn/ipnlocal+
tailscale.com/util/ringlog from tailscale.com/wgengine/magicsock
tailscale.com/util/set from tailscale.com/control/controlclient+
tailscale.com/util/singleflight from tailscale.com/control/controlclient+
tailscale.com/util/slicesx from tailscale.com/appc+
tailscale.com/util/syspolicy from tailscale.com/feature/syspolicy
tailscale.com/util/syspolicy/internal from tailscale.com/util/syspolicy+
tailscale.com/util/syspolicy/internal/loggerx from tailscale.com/util/syspolicy+
tailscale.com/util/syspolicy/internal/metrics from tailscale.com/util/syspolicy/source
tailscale.com/util/syspolicy/pkey from tailscale.com/control/controlclient+
tailscale.com/util/syspolicy/policyclient from tailscale.com/control/controlclient+
tailscale.com/util/syspolicy/ptype from tailscale.com/util/syspolicy+
tailscale.com/util/syspolicy/rsop from tailscale.com/ipn/localapi+
tailscale.com/util/syspolicy/setting from tailscale.com/client/local+
tailscale.com/util/syspolicy/source from tailscale.com/util/syspolicy+
tailscale.com/util/testenv from tailscale.com/control/controlclient+
tailscale.com/util/truncate from tailscale.com/logtail
tailscale.com/util/usermetric from tailscale.com/health+
tailscale.com/util/vizerror from tailscale.com/tailcfg+
💣 tailscale.com/util/winutil from tailscale.com/hostinfo+
W 💣 tailscale.com/util/winutil/authenticode from tailscale.com/util/osdiag
W 💣 tailscale.com/util/winutil/gp from tailscale.com/net/dns+
W tailscale.com/util/winutil/policy from tailscale.com/ipn/ipnlocal
W 💣 tailscale.com/util/winutil/winenv from tailscale.com/hostinfo+
tailscale.com/util/zstdframe from tailscale.com/control/controlclient+
tailscale.com/version from tailscale.com/client/web+
tailscale.com/version/distro from tailscale.com/client/web+
tailscale.com/wgengine from tailscale.com/ipn/ipnlocal+
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+
tailscale.com/wgengine/filter/filtertype from tailscale.com/types/netmap+
💣 tailscale.com/wgengine/magicsock from tailscale.com/ipn/ipnlocal+
tailscale.com/wgengine/netlog from tailscale.com/wgengine
tailscale.com/wgengine/netstack from tailscale.com/tsnet
tailscale.com/wgengine/netstack/gro from tailscale.com/net/tstun+
tailscale.com/wgengine/router from tailscale.com/ipn/ipnlocal+
tailscale.com/wgengine/wgcfg from tailscale.com/ipn/ipnlocal+
tailscale.com/wgengine/wgcfg/nmcfg from tailscale.com/ipn/ipnlocal
💣 tailscale.com/wgengine/wgint from tailscale.com/wgengine+
tailscale.com/wgengine/wglog from tailscale.com/wgengine
tailscale.com/wif from tailscale.com/feature/identityfederation
golang.org/x/crypto/argon2 from tailscale.com/tka
golang.org/x/crypto/blake2b from golang.org/x/crypto/argon2+
golang.org/x/crypto/blake2s from github.com/tailscale/wireguard-go/device+
LD golang.org/x/crypto/blowfish from golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/crypto/chacha20 from golang.org/x/crypto/chacha20poly1305+
golang.org/x/crypto/chacha20poly1305 from github.com/tailscale/wireguard-go/device+
golang.org/x/crypto/curve25519 from github.com/tailscale/wireguard-go/device+
golang.org/x/crypto/hkdf from tailscale.com/control/controlbase
golang.org/x/crypto/internal/alias from golang.org/x/crypto/chacha20+
golang.org/x/crypto/internal/poly1305 from golang.org/x/crypto/chacha20poly1305+
golang.org/x/crypto/nacl/box from tailscale.com/types/key
golang.org/x/crypto/nacl/secretbox from golang.org/x/crypto/nacl/box
golang.org/x/crypto/poly1305 from github.com/tailscale/wireguard-go/device
golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+
LD golang.org/x/crypto/ssh from tailscale.com/ipn/ipnlocal
LD golang.org/x/crypto/ssh/internal/bcrypt_pbkdf from golang.org/x/crypto/ssh
golang.org/x/exp/constraints from tailscale.com/tsweb/varz+
golang.org/x/exp/maps from tailscale.com/ipn/store/mem+
golang.org/x/net/bpf from github.com/mdlayher/netlink+
golang.org/x/net/dns/dnsmessage from tailscale.com/appc+
golang.org/x/net/http/httpguts from tailscale.com/ipn/ipnlocal
golang.org/x/net/http/httpproxy from tailscale.com/net/tshttpproxy
golang.org/x/net/icmp from github.com/prometheus-community/pro-bing+
golang.org/x/net/idna from golang.org/x/net/http/httpguts+
golang.org/x/net/internal/iana from golang.org/x/net/icmp+
golang.org/x/net/internal/socket from golang.org/x/net/icmp+
LDW golang.org/x/net/internal/socks from golang.org/x/net/proxy
golang.org/x/net/ipv4 from github.com/prometheus-community/pro-bing+
golang.org/x/net/ipv6 from github.com/prometheus-community/pro-bing+
LDW golang.org/x/net/proxy from tailscale.com/net/netns
DI golang.org/x/net/route from tailscale.com/net/netmon+
golang.org/x/oauth2 from golang.org/x/oauth2/clientcredentials+
golang.org/x/oauth2/clientcredentials from tailscale.com/feature/oauthkey
golang.org/x/oauth2/internal from golang.org/x/oauth2+
golang.org/x/sync/errgroup from github.com/mdlayher/socket+
golang.org/x/sys/cpu from github.com/tailscale/certstore+
LDAI golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+
W golang.org/x/sys/windows from github.com/dblohm7/wingoes+
W golang.org/x/sys/windows/registry from github.com/dblohm7/wingoes+
W golang.org/x/sys/windows/svc from golang.org/x/sys/windows/svc/mgr+
W golang.org/x/sys/windows/svc/mgr from tailscale.com/util/winutil
golang.org/x/term from tailscale.com/logpolicy
golang.org/x/text/secure/bidirule from golang.org/x/net/idna
golang.org/x/text/transform from golang.org/x/text/secure/bidirule+
golang.org/x/text/unicode/bidi from golang.org/x/net/idna+
golang.org/x/text/unicode/norm from golang.org/x/net/idna
golang.org/x/time/rate from gvisor.dev/gvisor/pkg/log+
vendor/golang.org/x/crypto/chacha20 from vendor/golang.org/x/crypto/chacha20poly1305
vendor/golang.org/x/crypto/chacha20poly1305 from crypto/internal/hpke+
vendor/golang.org/x/crypto/cryptobyte from crypto/ecdsa+
vendor/golang.org/x/crypto/cryptobyte/asn1 from crypto/ecdsa+
vendor/golang.org/x/crypto/internal/alias from vendor/golang.org/x/crypto/chacha20+
vendor/golang.org/x/crypto/internal/poly1305 from vendor/golang.org/x/crypto/chacha20poly1305
vendor/golang.org/x/net/dns/dnsmessage from net
vendor/golang.org/x/net/http/httpguts from net/http+
vendor/golang.org/x/net/http/httpproxy from net/http
vendor/golang.org/x/net/http2/hpack from net/http+
vendor/golang.org/x/net/idna from net/http+
vendor/golang.org/x/sys/cpu from vendor/golang.org/x/crypto/chacha20poly1305
vendor/golang.org/x/text/secure/bidirule from vendor/golang.org/x/net/idna
vendor/golang.org/x/text/transform from vendor/golang.org/x/text/secure/bidirule+
vendor/golang.org/x/text/unicode/bidi from vendor/golang.org/x/net/idna+
vendor/golang.org/x/text/unicode/norm from vendor/golang.org/x/net/idna
bufio from compress/flate+
bytes from bufio+
cmp from encoding/json+
compress/flate from compress/gzip+
compress/gzip from internal/profile+
W compress/zlib from debug/pe
container/heap from gvisor.dev/gvisor/pkg/tcpip/transport/tcp
container/list from crypto/tls+
context from crypto/tls+
crypto from crypto/ecdh+
crypto/aes from crypto/internal/hpke+
crypto/cipher from crypto/aes+
crypto/des from crypto/tls+
crypto/dsa from crypto/x509+
crypto/ecdh from crypto/ecdsa+
crypto/ecdsa from crypto/tls+
crypto/ed25519 from crypto/tls+
crypto/elliptic from crypto/ecdsa+
crypto/fips140 from crypto/tls/internal/fips140tls+
crypto/hkdf from crypto/internal/hpke+
crypto/hmac from crypto/tls+
crypto/internal/boring from crypto/aes+
crypto/internal/boring/bbig from crypto/ecdsa+
crypto/internal/boring/sig from crypto/internal/boring
crypto/internal/entropy from crypto/internal/fips140/drbg
crypto/internal/fips140 from crypto/internal/fips140/aes+
crypto/internal/fips140/aes from crypto/aes+
crypto/internal/fips140/aes/gcm from crypto/cipher+
crypto/internal/fips140/alias from crypto/cipher+
crypto/internal/fips140/bigmod from crypto/internal/fips140/ecdsa+
crypto/internal/fips140/check from crypto/internal/fips140/aes+
crypto/internal/fips140/drbg from crypto/internal/fips140/aes/gcm+
crypto/internal/fips140/ecdh from crypto/ecdh
crypto/internal/fips140/ecdsa from crypto/ecdsa
crypto/internal/fips140/ed25519 from crypto/ed25519
crypto/internal/fips140/edwards25519 from crypto/internal/fips140/ed25519
crypto/internal/fips140/edwards25519/field from crypto/ecdh+
crypto/internal/fips140/hkdf from crypto/internal/fips140/tls13+
crypto/internal/fips140/hmac from crypto/hmac+
crypto/internal/fips140/mlkem from crypto/tls+
crypto/internal/fips140/nistec from crypto/elliptic+
crypto/internal/fips140/nistec/fiat from crypto/internal/fips140/nistec
crypto/internal/fips140/rsa from crypto/rsa
crypto/internal/fips140/sha256 from crypto/internal/fips140/check+
crypto/internal/fips140/sha3 from crypto/internal/fips140/hmac+
crypto/internal/fips140/sha512 from crypto/internal/fips140/ecdsa+
crypto/internal/fips140/subtle from crypto/internal/fips140/aes+
crypto/internal/fips140/tls12 from crypto/tls
crypto/internal/fips140/tls13 from crypto/tls
crypto/internal/fips140cache from crypto/ecdsa+
crypto/internal/fips140deps/byteorder from crypto/internal/fips140/aes+
crypto/internal/fips140deps/cpu from crypto/internal/fips140/aes+
crypto/internal/fips140deps/godebug from crypto/internal/fips140+
crypto/internal/fips140hash from crypto/ecdsa+
crypto/internal/fips140only from crypto/cipher+
crypto/internal/hpke from crypto/tls
crypto/internal/impl from crypto/internal/fips140/aes+
crypto/internal/randutil from crypto/dsa+
crypto/internal/sysrand from crypto/internal/entropy+
crypto/md5 from crypto/tls+
LD crypto/mlkem from golang.org/x/crypto/ssh
crypto/rand from crypto/ed25519+
crypto/rc4 from crypto/tls+
crypto/rsa from crypto/tls+
crypto/sha1 from crypto/tls+
crypto/sha256 from crypto/tls+
crypto/sha3 from crypto/internal/fips140hash
crypto/sha512 from crypto/ecdsa+
crypto/subtle from crypto/cipher+
crypto/tls from github.com/prometheus-community/pro-bing+
crypto/tls/internal/fips140tls from crypto/tls
crypto/x509 from crypto/tls+
DI crypto/x509/internal/macos from crypto/x509
crypto/x509/pkix from crypto/x509+
DI database/sql/driver from github.com/google/uuid
W debug/dwarf from debug/pe
W debug/pe from github.com/dblohm7/wingoes/pe
embed from github.com/tailscale/web-client-prebuilt+
encoding from encoding/json+
encoding/asn1 from crypto/x509+
encoding/base32 from github.com/fxamacker/cbor/v2+
encoding/base64 from encoding/json+
encoding/binary from compress/gzip+
encoding/hex from crypto/x509+
encoding/json from expvar+
encoding/pem from crypto/tls+
encoding/xml from github.com/huin/goupnp+
errors from bufio+
expvar from tailscale.com/health+
flag from tailscale.com/util/testenv
fmt from compress/flate+
hash from crypto+
W hash/adler32 from compress/zlib
hash/crc32 from compress/gzip+
hash/maphash from go4.org/mem
html from html/template+
LDW html/template from tailscale.com/util/eventbus
internal/abi from crypto/x509/internal/macos+
internal/asan from internal/runtime/maps+
internal/bisect from internal/godebug
internal/bytealg from bytes+
internal/byteorder from crypto/cipher+
internal/chacha8rand from math/rand/v2+
internal/coverage/rtcov from runtime
internal/cpu from crypto/internal/fips140deps/cpu+
internal/filepathlite from os+
internal/fmtsort from fmt+
internal/goarch from crypto/internal/fips140deps/cpu+
internal/godebug from crypto/internal/fips140deps/godebug+
internal/godebugs from internal/godebug+
internal/goexperiment from hash/maphash+
internal/goos from crypto/x509+
internal/itoa from internal/poll+
internal/msan from internal/runtime/maps+
internal/nettrace from net+
internal/oserror from io/fs+
internal/poll from net+
LDW internal/profile from net/http/pprof
internal/profilerecord from runtime+
internal/race from internal/poll+
internal/reflectlite from context+
DI internal/routebsd from net
internal/runtime/atomic from internal/runtime/exithook+
LA internal/runtime/cgroup from runtime
internal/runtime/exithook from runtime
internal/runtime/gc from runtime
internal/runtime/maps from reflect+
internal/runtime/math from internal/runtime/maps+
internal/runtime/strconv from internal/runtime/cgroup+
internal/runtime/sys from crypto/subtle+
LA internal/runtime/syscall from runtime+
internal/saferio from debug/pe+
internal/singleflight from net
internal/stringslite from embed+
internal/sync from sync+
internal/synctest from sync
internal/syscall/execenv from os+
LDAI internal/syscall/unix from crypto/internal/sysrand+
W internal/syscall/windows from crypto/internal/sysrand+
W internal/syscall/windows/registry from mime+
W internal/syscall/windows/sysdll from internal/syscall/windows+
internal/testlog from os
internal/trace/tracev2 from runtime+
internal/unsafeheader from internal/reflectlite+
io from bufio+
io/fs from crypto/x509+
io/ioutil from github.com/godbus/dbus/v5+
iter from bytes+
log from expvar+
log/internal from log
maps from crypto/x509+
math from compress/flate+
math/big from crypto/dsa+
math/bits from bytes+
math/rand from github.com/fxamacker/cbor/v2+
math/rand/v2 from crypto/ecdsa+
mime from mime/multipart+
mime/multipart from net/http
mime/quotedprintable from mime/multipart
net from crypto/tls+
net/http from expvar+
net/http/httptrace from github.com/prometheus-community/pro-bing+
net/http/httputil from tailscale.com/client/web+
net/http/internal from net/http+
net/http/internal/ascii from net/http+
net/http/internal/httpcommon from net/http
LDW net/http/pprof from tailscale.com/ipn/localapi+
net/netip from crypto/x509+
net/textproto from github.com/coder/websocket+
net/url from crypto/x509+
os from crypto/internal/sysrand+
os/exec from github.com/godbus/dbus/v5+
os/user from github.com/godbus/dbus/v5+
path from debug/dwarf+
path/filepath from crypto/x509+
reflect from crypto/x509+
regexp from github.com/huin/goupnp/httpu+
regexp/syntax from regexp
runtime from crypto/internal/fips140+
runtime/debug from github.com/coder/websocket/internal/xsync+
runtime/pprof from net/http/pprof+
LDW runtime/trace from net/http/pprof
slices from crypto/tls+
sort from compress/flate+
strconv from compress/flate+
strings from bufio+
W structs from internal/syscall/windows
sync from compress/flate+
sync/atomic from context+
syscall from crypto/internal/sysrand+
text/tabwriter from runtime/pprof
LDW text/template from html/template
LDW text/template/parse from html/template+
time from compress/gzip+
unicode from bytes+
unicode/utf16 from crypto/x509+
unicode/utf8 from bufio+
unique from net/netip
unsafe from bytes+
weak from unique+

690
vendor/tailscale.com/tsnet/tsnet.go generated vendored
View File

@@ -27,12 +27,16 @@ import (
"time"
"tailscale.com/client/local"
"tailscale.com/client/tailscale"
"tailscale.com/control/controlclient"
"tailscale.com/envknob"
_ "tailscale.com/feature/condregister"
_ "tailscale.com/feature/c2n"
_ "tailscale.com/feature/condregister/identityfederation"
_ "tailscale.com/feature/condregister/oauthkey"
_ "tailscale.com/feature/condregister/portmapper"
_ "tailscale.com/feature/condregister/useproxy"
"tailscale.com/health"
"tailscale.com/hostinfo"
"tailscale.com/internal/client/tailscale"
"tailscale.com/ipn"
"tailscale.com/ipn/ipnauth"
"tailscale.com/ipn/ipnlocal"
@@ -48,6 +52,7 @@ import (
"tailscale.com/net/proxymux"
"tailscale.com/net/socks5"
"tailscale.com/net/tsdial"
"tailscale.com/tailcfg"
"tailscale.com/tsd"
"tailscale.com/types/bools"
"tailscale.com/types/logger"
@@ -112,6 +117,37 @@ type Server struct {
// used.
AuthKey string
// ClientSecret, if non-empty, is the OAuth client secret
// that will be used to generate authkeys via OAuth. It
// will be preferred over the TS_CLIENT_SECRET environment
// variable. If the node is already created (from state
// previously stored in Store), then this field is not
// used.
ClientSecret string
// ClientID, if non-empty, is the client ID used to generate
// authkeys via workload identity federation. It will be
// preferred over the TS_CLIENT_ID environment variable.
// If the node is already created (from state previously
// stored in Store), then this field is not used.
ClientID string
// IDToken, if non-empty, is the ID token from the identity
// provider to exchange with the control server for workload
// identity federation. It will be preferred over the
// TS_ID_TOKEN environment variable. If the node is already
// created (from state previously stored in Store), then this
// field is not used.
IDToken string
// Audience, if non-empty, is the audience to use when requesting
// an ID token from a well-known identity provider to exchange
// with the control server for workload identity federation. It
// will be preferred over the TS_AUDIENCE environment variable. If
// the node is already created (from state previously stored in Store),
// then this field is not used.
Audience string
// ControlURL optionally specifies the coordination server URL.
// If empty, the Tailscale default is used.
ControlURL string
@@ -125,27 +161,32 @@ type Server struct {
// field at zero unless you know what you are doing.
Port uint16
getCertForTesting func(*tls.ClientHelloInfo) (*tls.Certificate, error)
// AdvertiseTags specifies tags that should be applied to this node, for
// purposes of ACL enforcement. These can be referenced from the ACL policy
// document. Note that advertising a tag on the client doesn't guarantee
// that the control server will allow the node to adopt that tag.
AdvertiseTags []string
initOnce sync.Once
initErr error
lb *ipnlocal.LocalBackend
sys *tsd.System
netstack *netstack.Impl
netMon *netmon.Monitor
rootPath string // the state directory
hostname string
shutdownCtx context.Context
shutdownCancel context.CancelFunc
proxyCred string // SOCKS5 proxy auth for loopbackListener
localAPICred string // basic auth password for loopbackListener
loopbackListener net.Listener // optional loopback for localapi and proxies
localAPIListener net.Listener // in-memory, used by localClient
localClient *local.Client // in-memory
localAPIServer *http.Server
logbuffer *filch.Filch
logtail *logtail.Logger
logid logid.PublicID
initOnce sync.Once
initErr error
lb *ipnlocal.LocalBackend
sys *tsd.System
netstack *netstack.Impl
netMon *netmon.Monitor
rootPath string // the state directory
hostname string
shutdownCtx context.Context
shutdownCancel context.CancelFunc
proxyCred string // SOCKS5 proxy auth for loopbackListener
localAPICred string // basic auth password for loopbackListener
loopbackListener net.Listener // optional loopback for localapi and proxies
localAPIListener net.Listener // in-memory, used by localClient
localClient *local.Client // in-memory
localAPIServer *http.Server
resetServeConfigOnce sync.Once
logbuffer *filch.Filch
logtail *logtail.Logger
logid logid.PublicID
mu sync.Mutex
listeners map[listenKey]*listener
@@ -275,7 +316,13 @@ func (s *Server) Loopback() (addr string, proxyCred, localAPICred string, err er
// out the CONNECT code from tailscaled/proxy.go that uses
// httputil.ReverseProxy and adding auth support.
go func() {
lah := localapi.NewHandler(ipnauth.Self, s.lb, s.logf, s.logid)
lah := localapi.NewHandler(localapi.HandlerConfig{
Actor: ipnauth.Self,
Backend: s.lb,
Logf: s.logf,
LogID: s.logid,
EventBus: s.sys.Bus.Get(),
})
lah.PermitWrite = true
lah.PermitRead = true
lah.RequiredPassword = s.localAPICred
@@ -335,7 +382,7 @@ func (s *Server) Up(ctx context.Context) (*ipnstate.Status, error) {
return nil, fmt.Errorf("tsnet.Up: %w", err)
}
watcher, err := lc.WatchIPNBus(ctx, ipn.NotifyInitialState|ipn.NotifyNoPrivateKeys)
watcher, err := lc.WatchIPNBus(ctx, ipn.NotifyInitialState)
if err != nil {
return nil, fmt.Errorf("tsnet.Up: %w", err)
}
@@ -349,8 +396,8 @@ func (s *Server) Up(ctx context.Context) (*ipnstate.Status, error) {
if n.ErrMessage != nil {
return nil, fmt.Errorf("tsnet.Up: backend: %s", *n.ErrMessage)
}
if s := n.State; s != nil {
if *s == ipn.Running {
if st := n.State; st != nil {
if *st == ipn.Running {
status, err := lc.Status(ctx)
if err != nil {
return nil, fmt.Errorf("tsnet.Up: %w", err)
@@ -359,11 +406,15 @@ func (s *Server) Up(ctx context.Context) (*ipnstate.Status, error) {
return nil, errors.New("tsnet.Up: running, but no ip")
}
// Clear the persisted serve config state to prevent stale configuration
// from code changes. This is a temporary workaround until we have a better
// way to handle this. (2023-03-11)
if err := lc.SetServeConfig(ctx, new(ipn.ServeConfig)); err != nil {
return nil, fmt.Errorf("tsnet.Up: %w", err)
// The first time Up is run, clear the persisted serve config.
// We do this to prevent messy interactions with stale config in
// the face of code changes.
var srvResetErr error
s.resetServeConfigOnce.Do(func() {
srvResetErr = lc.SetServeConfig(ctx, new(ipn.ServeConfig))
})
if srvResetErr != nil {
return nil, fmt.Errorf("tsnet.Up: clearing serve config: %w", err)
}
return status, nil
@@ -435,8 +486,8 @@ func (s *Server) Close() error {
for _, ln := range s.listeners {
ln.closeLocked()
}
wg.Wait()
s.sys.Bus.Get().Close()
s.closed = true
return nil
}
@@ -482,6 +533,16 @@ func (s *Server) TailscaleIPs() (ip4, ip6 netip.Addr) {
return ip4, ip6
}
// LogtailWriter returns an [io.Writer] that writes to Tailscale's logging service and will be only visible to Tailscale's
// support team. Logs written there cannot be retrieved by the user. This method always returns a non-nil value.
func (s *Server) LogtailWriter() io.Writer {
if s.logtail == nil {
return io.Discard
}
return s.logtail
}
func (s *Server) getAuthKey() string {
if v := s.AuthKey; v != "" {
return v
@@ -492,6 +553,34 @@ func (s *Server) getAuthKey() string {
return os.Getenv("TS_AUTH_KEY")
}
func (s *Server) getClientSecret() string {
if v := s.ClientSecret; v != "" {
return v
}
return os.Getenv("TS_CLIENT_SECRET")
}
func (s *Server) getClientID() string {
if v := s.ClientID; v != "" {
return v
}
return os.Getenv("TS_CLIENT_ID")
}
func (s *Server) getIDToken() string {
if v := s.IDToken; v != "" {
return v
}
return os.Getenv("TS_ID_TOKEN")
}
func (s *Server) getAudience() string {
if v := s.Audience; v != "" {
return v
}
return os.Getenv("TS_AUDIENCE")
}
func (s *Server) start() (reterr error) {
var closePool closeOnErrorPool
defer closePool.closeAllIfError(&reterr)
@@ -534,10 +623,7 @@ func (s *Server) start() (reterr error) {
if err != nil {
return err
}
s.rootPath, err = getTSNetDir(s.logf, confDir, prog)
if err != nil {
return err
}
s.rootPath = filepath.Join(confDir, "tsnet-"+prog)
}
if err := os.MkdirAll(s.rootPath, 0700); err != nil {
return err
@@ -558,26 +644,28 @@ func (s *Server) start() (reterr error) {
s.Logf(format, a...)
}
sys := new(tsd.System)
sys := tsd.NewSystem()
s.sys = sys
if err := s.startLogger(&closePool, sys.HealthTracker(), tsLogf); err != nil {
if err := s.startLogger(&closePool, sys.HealthTracker.Get(), tsLogf); err != nil {
return err
}
s.netMon, err = netmon.New(tsLogf)
s.netMon, err = netmon.New(sys.Bus.Get(), tsLogf)
if err != nil {
return err
}
closePool.add(s.netMon)
s.dialer = &tsdial.Dialer{Logf: tsLogf} // mutated below (before used)
s.dialer.SetBus(sys.Bus.Get())
eng, err := wgengine.NewUserspaceEngine(tsLogf, wgengine.Config{
EventBus: sys.Bus.Get(),
ListenPort: s.Port,
NetMon: s.netMon,
Dialer: s.dialer,
SetSubsystem: sys.Set,
ControlKnobs: sys.ControlKnobs(),
HealthTracker: sys.HealthTracker(),
HealthTracker: sys.HealthTracker.Get(),
Metrics: sys.UserMetricsRegistry(),
})
if err != nil {
@@ -585,7 +673,7 @@ func (s *Server) start() (reterr error) {
}
closePool.add(s.dialer)
sys.Set(eng)
sys.HealthTracker().SetMetricsRegistry(sys.UserMetricsRegistry())
sys.HealthTracker.Get().SetMetricsRegistry(sys.UserMetricsRegistry())
// TODO(oxtoacart): do we need to support Taildrive on tsnet, and if so, how?
ns, err := netstack.Create(tsLogf, sys.Tun.Get(), eng, sys.MagicSock.Get(), s.dialer, sys.DNSManager.Get(), sys.ProxyMapper())
@@ -659,7 +747,11 @@ func (s *Server) start() (reterr error) {
prefs.WantRunning = true
prefs.ControlURL = s.ControlURL
prefs.RunWebClient = s.RunWebClient
authKey := s.getAuthKey()
prefs.AdvertiseTags = s.AdvertiseTags
authKey, err := s.resolveAuthKey()
if err != nil {
return fmt.Errorf("error resolving auth key: %w", err)
}
err = lb.Start(ipn.Options{
UpdatePrefs: prefs,
AuthKey: authKey,
@@ -679,7 +771,13 @@ func (s *Server) start() (reterr error) {
go s.printAuthURLLoop()
// Run the localapi handler, to allow fetching LetsEncrypt certs.
lah := localapi.NewHandler(ipnauth.Self, lb, tsLogf, s.logid)
lah := localapi.NewHandler(localapi.HandlerConfig{
Actor: ipnauth.Self,
Backend: lb,
Logf: tsLogf,
LogID: s.logid,
EventBus: sys.Bus.Get(),
})
lah.PermitWrite = true
lah.PermitRead = true
@@ -699,6 +797,51 @@ func (s *Server) start() (reterr error) {
return nil
}
func (s *Server) resolveAuthKey() (string, error) {
authKey := s.getAuthKey()
var err error
// Try to use an OAuth secret to generate an auth key if that functionality
// is available.
resolveViaOAuth, oauthOk := tailscale.HookResolveAuthKey.GetOk()
if oauthOk {
clientSecret := authKey
if authKey == "" {
clientSecret = s.getClientSecret()
}
authKey, err = resolveViaOAuth(s.shutdownCtx, clientSecret, s.AdvertiseTags)
if err != nil {
return "", err
}
}
// Try to resolve the auth key via workload identity federation if that functionality
// is available and no auth key is yet determined.
resolveViaWIF, wifOk := tailscale.HookResolveAuthKeyViaWIF.GetOk()
if wifOk && authKey == "" {
clientID := s.getClientID()
idToken := s.getIDToken()
audience := s.getAudience()
if clientID != "" && idToken == "" && audience == "" {
return "", fmt.Errorf("client ID for workload identity federation found, but ID token and audience are empty")
}
if idToken != "" && audience != "" {
return "", fmt.Errorf("only one of ID token and audience should be for workload identity federation")
}
if clientID == "" {
if idToken != "" {
return "", fmt.Errorf("ID token for workload identity federation found, but client ID is empty")
}
if audience != "" {
return "", fmt.Errorf("audience for workload identity federation found, but client ID is empty")
}
}
authKey, err = resolveViaWIF(s.shutdownCtx, s.ControlURL, clientID, idToken, audience, s.AdvertiseTags)
if err != nil {
return "", err
}
}
return authKey, nil
}
func (s *Server) startLogger(closePool *closeOnErrorPool, health *health.Tracker, tsLogf logger.Logf) error {
if testenv.InTest() {
return nil
@@ -730,6 +873,7 @@ func (s *Server) startLogger(closePool *closeOnErrorPool, health *health.Tracker
Stderr: io.Discard, // log everything to Buffer
Buffer: s.logbuffer,
CompressLogs: true,
Bus: s.sys.Bus.Get(),
HTTPC: &http.Client{Transport: logpolicy.NewLogtailTransport(logtail.DefaultHost, s.netMon, health, tsLogf)},
MetricsDelta: clientmetric.EncodeLogTailMetricsDelta,
}
@@ -894,103 +1038,6 @@ func (s *Server) getUDPHandlerForFlow(src, dst netip.AddrPort) (handler func(net
return func(c nettype.ConnPacketConn) { ln.handle(c) }, true
}
// getTSNetDir usually just returns filepath.Join(confDir, "tsnet-"+prog)
// with no error.
//
// One special case is that it renames old "tslib-" directories to
// "tsnet-", and that rename might return an error.
//
// TODO(bradfitz): remove this maybe 6 months after 2022-03-17,
// once people (notably Tailscale corp services) have updated.
func getTSNetDir(logf logger.Logf, confDir, prog string) (string, error) {
oldPath := filepath.Join(confDir, "tslib-"+prog)
newPath := filepath.Join(confDir, "tsnet-"+prog)
fi, err := os.Lstat(oldPath)
if os.IsNotExist(err) {
// Common path.
return newPath, nil
}
if err != nil {
return "", err
}
if !fi.IsDir() {
return "", fmt.Errorf("expected old tslib path %q to be a directory; got %v", oldPath, fi.Mode())
}
// At this point, oldPath exists and is a directory. But does
// the new path exist?
fi, err = os.Lstat(newPath)
if err == nil && fi.IsDir() {
// New path already exists somehow. Ignore the old one and
// don't try to migrate it.
return newPath, nil
}
if err != nil && !os.IsNotExist(err) {
return "", err
}
if err := os.Rename(oldPath, newPath); err != nil {
return "", err
}
logf("renamed old tsnet state storage directory %q to %q", oldPath, newPath)
return newPath, nil
}
// APIClient returns a tailscale.Client that can be used to make authenticated
// requests to the Tailscale control server.
// It requires the user to set tailscale.I_Acknowledge_This_API_Is_Unstable.
//
// Deprecated: use AuthenticatedAPITransport with tailscale.com/client/tailscale/v2 instead.
func (s *Server) APIClient() (*tailscale.Client, error) {
if !tailscale.I_Acknowledge_This_API_Is_Unstable {
return nil, errors.New("use of Client without setting I_Acknowledge_This_API_Is_Unstable")
}
if err := s.Start(); err != nil {
return nil, err
}
c := tailscale.NewClient("-", nil)
c.UserAgent = "tailscale-tsnet"
c.HTTPClient = &http.Client{Transport: s.lb.KeyProvingNoiseRoundTripper()}
return c, nil
}
// I_Acknowledge_This_API_Is_Experimental must be set true to use AuthenticatedAPITransport()
// for now.
var I_Acknowledge_This_API_Is_Experimental = false
// AuthenticatedAPITransport provides an HTTP transport that can be used with
// the control server API without needing additional authentication details. It
// authenticates using the current client's nodekey.
//
// It requires the user to set I_Acknowledge_This_API_Is_Experimental.
//
// For example:
//
// import "net/http"
// import "tailscale.com/client/tailscale/v2"
// import "tailscale.com/tsnet"
//
// var s *tsnet.Server
// ...
// rt, err := s.AuthenticatedAPITransport()
// // handler err ...
// var client tailscale.Client{HTTP: http.Client{
// Timeout: 1*time.Minute,
// UserAgent: "your-useragent-here",
// Transport: rt,
// }}
func (s *Server) AuthenticatedAPITransport() (http.RoundTripper, error) {
if !I_Acknowledge_This_API_Is_Experimental {
return nil, errors.New("use of AuthenticatedAPITransport without setting I_Acknowledge_This_API_Is_Experimental")
}
if err := s.Start(); err != nil {
return nil, err
}
return s.lb.KeyProvingNoiseRoundTripper(), nil
}
// Listen announces only on the Tailscale network.
// It will start the server if it has not been started yet.
//
@@ -1082,9 +1129,6 @@ func (s *Server) RegisterFallbackTCPHandler(cb FallbackTCPHandler) func() {
// It calls GetCertificate on the localClient, passing in the ClientHelloInfo.
// For testing, if s.getCertForTesting is set, it will call that instead.
func (s *Server) getCert(hi *tls.ClientHelloInfo) (*tls.Certificate, error) {
if s.getCertForTesting != nil {
return s.getCertForTesting(hi)
}
lc, err := s.LocalClient()
if err != nil {
return nil, err
@@ -1097,13 +1141,33 @@ type FunnelOption interface {
funnelOption()
}
type funnelOnly int
type funnelOnly struct{}
func (funnelOnly) funnelOption() {}
// FunnelOnly configures the listener to only respond to connections from Tailscale Funnel.
// The local tailnet will not be able to connect to the listener.
func FunnelOnly() FunnelOption { return funnelOnly(1) }
func FunnelOnly() FunnelOption { return funnelOnly{} }
type funnelTLSConfig struct{ conf *tls.Config }
func (f funnelTLSConfig) funnelOption() {}
// FunnelTLSConfig configures the TLS configuration for [Server.ListenFunnel]
//
// This is rarely needed but can permit requiring client certificates, specific
// ciphers suites, etc.
//
// The provided conf should at least be able to get a certificate, setting
// GetCertificate, Certificates or GetConfigForClient appropriately.
// The most common configuration is to set GetCertificate to
// Server.LocalClient's GetCertificate method.
//
// Unless [FunnelOnly] is also used, the configuration is also used for
// in-tailnet connections that don't arrive over Funnel.
func FunnelTLSConfig(conf *tls.Config) FunnelOption {
return funnelTLSConfig{conf: conf}
}
// ListenFunnel announces on the public internet using Tailscale Funnel.
//
@@ -1136,6 +1200,26 @@ func (s *Server) ListenFunnel(network, addr string, opts ...FunnelOption) (net.L
return nil, err
}
// Process, validate opts.
lnOn := listenOnBoth
var tlsConfig *tls.Config
for _, opt := range opts {
switch v := opt.(type) {
case funnelTLSConfig:
if v.conf == nil {
return nil, errors.New("invalid nil FunnelTLSConfig")
}
tlsConfig = v.conf
case funnelOnly:
lnOn = listenOnFunnel
default:
return nil, fmt.Errorf("unknown opts FunnelOption type %T", v)
}
}
if tlsConfig == nil {
tlsConfig = &tls.Config{GetCertificate: s.getCert}
}
ctx := context.Background()
st, err := s.Up(ctx)
if err != nil {
@@ -1164,28 +1248,288 @@ func (s *Server) ListenFunnel(network, addr string, opts ...FunnelOption) (net.L
}
domain := st.CertDomains[0]
hp := ipn.HostPort(domain + ":" + portStr)
var cleanupOnClose func() error
if !srvConfig.AllowFunnel[hp] {
mak.Set(&srvConfig.AllowFunnel, hp, true)
srvConfig.AllowFunnel[hp] = true
if err := lc.SetServeConfig(ctx, srvConfig); err != nil {
return nil, err
}
cleanupOnClose = func() error {
sc, err := lc.GetServeConfig(ctx)
if err != nil {
return fmt.Errorf("cleaning config changes: %w", err)
}
if sc.AllowFunnel != nil {
delete(sc.AllowFunnel, hp)
}
if err := lc.SetServeConfig(ctx, sc); err != nil {
return fmt.Errorf("cleaning config changes: %w", err)
}
return nil
}
}
// Start a funnel listener.
lnOn := listenOnBoth
for _, opt := range opts {
if _, ok := opt.(funnelOnly); ok {
lnOn = listenOnFunnel
}
}
ln, err := s.listen(network, addr, lnOn)
if err != nil {
return nil, err
}
return tls.NewListener(ln, &tls.Config{
GetCertificate: s.getCert,
}), nil
ln = &cleanupListener{Listener: ln, cleanup: cleanupOnClose}
return tls.NewListener(ln, tlsConfig), nil
}
// ServiceMode defines how a Service is run. Currently supported modes are:
// - [ServiceModeTCP]
// - [ServiceModeHTTP]
//
// For more information, see [Server.ListenService].
type ServiceMode interface {
// network is the network this Service will advertise on. Per Go convention,
// this should be lowercase, e.g. 'tcp'.
network() string
}
// serviceModeWithPort is a convenience type to extract the port from
// ServiceMode types which have one.
type serviceModeWithPort interface {
ServiceMode
port() uint16
}
// ServiceModeTCP is used to configure a TCP Service via [Server.ListenService].
type ServiceModeTCP struct {
// Port is the TCP port to advertise. If this Service needs to advertise
// multiple ports, call ListenService multiple times.
Port uint16
// TerminateTLS means that TLS connections will be terminated before being
// forwarded to the listener. In this case, the only server name indicator
// (SNI) permitted is the Service's fully-qualified domain name.
TerminateTLS bool
// PROXYProtocolVersion indicates whether to send a PROXY protocol header
// before forwarding the connection to the listener and which version of the
// protocol to use.
//
// For more information, see
// https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
PROXYProtocolVersion int
}
func (ServiceModeTCP) network() string { return "tcp" }
func (m ServiceModeTCP) port() uint16 { return m.Port }
// ServiceModeHTTP is used to configure an HTTP Service via
// [Server.ListenService].
type ServiceModeHTTP struct {
// Port is the TCP port to advertise. If this Service needs to advertise
// multiple ports, call ListenService multiple times.
Port uint16
// HTTPS, if true, means that the listener should handle connections as
// HTTPS connections. In this case, the only server name indicator (SNI)
// permitted is the Service's fully-qualified domain name.
HTTPS bool
// AcceptAppCaps defines the app capabilities to forward to the server. The
// keys in this map are the mount points for each set of capabilities.
//
// By example,
//
// AcceptAppCaps: map[string][]string{
// "/": {"example.com/cap/all-paths"},
// "/foo": {"example.com/cap/all-paths", "example.com/cap/foo"},
// }
//
// would forward example.com/cap/all-paths to all paths on the server and
// example.com/cap/foo only to paths beginning with /foo.
//
// For more information on app capabilities, see
// https://tailscale.com/kb/1537/grants-app-capabilities
AcceptAppCaps map[string][]string
// PROXYProtocolVersion indicates whether to send a PROXY protocol header
// before forwarding the connection to the listener and which version of the
// protocol to use.
//
// For more information, see
// https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
PROXYProtocol int
}
func (ServiceModeHTTP) network() string { return "tcp" }
func (m ServiceModeHTTP) port() uint16 { return m.Port }
func (m ServiceModeHTTP) capsMap() map[string][]tailcfg.PeerCapability {
capsMap := map[string][]tailcfg.PeerCapability{}
for path, capNames := range m.AcceptAppCaps {
caps := make([]tailcfg.PeerCapability, 0, len(capNames))
for _, c := range capNames {
caps = append(caps, tailcfg.PeerCapability(c))
}
capsMap[path] = caps
}
return capsMap
}
// A ServiceListener is a network listener for a Tailscale Service. For more
// information about Services, see
// https://tailscale.com/kb/1552/tailscale-services
type ServiceListener struct {
net.Listener
addr addr
// FQDN is the fully-qualifed domain name of this Service.
FQDN string
}
// Addr returns the listener's network address. This will be the Service's
// fully-qualified domain name (FQDN) and the port.
//
// A hostname is not truly a network address, but Services listen on multiple
// addresses (the IPv4 and IPv6 virtual IPs).
func (sl ServiceListener) Addr() net.Addr {
return sl.addr
}
// ErrUntaggedServiceHost is returned by ListenService when run on a node
// without any ACL tags. A node must use a tag-based identity to act as a
// Service host. For more information, see:
// https://tailscale.com/kb/1552/tailscale-services#prerequisites
var ErrUntaggedServiceHost = errors.New("service hosts must be tagged nodes")
// ListenService creates a network listener for a Tailscale Service. This will
// advertise this node as hosting the Service. Note that:
// - Approval must still be granted by an admin or by ACL auto-approval rules.
// - Service hosts must be tagged nodes.
// - A valid Service host must advertise all ports defined for the Service.
//
// To advertise a Service with multiple ports, run ListenService multiple times.
// For more information about Services, see
// https://tailscale.com/kb/1552/tailscale-services
func (s *Server) ListenService(name string, mode ServiceMode) (*ServiceListener, error) {
if err := tailcfg.ServiceName(name).Validate(); err != nil {
return nil, err
}
if mode == nil {
return nil, errors.New("mode may not be nil")
}
svcName := name
// TODO(hwh33,tailscale/corp#35859): support TUN mode
ctx := context.Background()
_, err := s.Up(ctx)
if err != nil {
return nil, err
}
st := s.lb.StatusWithoutPeers()
if st.Self.Tags == nil || st.Self.Tags.Len() == 0 {
return nil, ErrUntaggedServiceHost
}
advertisedServices := s.lb.Prefs().AdvertiseServices().AsSlice()
if !slices.Contains(advertisedServices, svcName) {
// TODO(hwh33,tailscale/corp#35860): clean these prefs up when (a) we
// exit early due to error or (b) when the returned listener is closed.
_, err = s.lb.EditPrefs(&ipn.MaskedPrefs{
AdvertiseServicesSet: true,
Prefs: ipn.Prefs{
AdvertiseServices: append(advertisedServices, svcName),
},
})
if err != nil {
return nil, fmt.Errorf("updating advertised Services: %w", err)
}
}
srvConfig := new(ipn.ServeConfig)
sc, srvConfigETag, err := s.lb.ServeConfigETag()
if err != nil {
return nil, fmt.Errorf("fetching current serve config: %w", err)
}
if sc.Valid() {
srvConfig = sc.AsStruct()
}
fqdn := tailcfg.ServiceName(svcName).WithoutPrefix() + "." + st.CurrentTailnet.MagicDNSSuffix
// svcAddr is used to implement Addr() on the returned listener.
svcAddr := addr{
network: mode.network(),
// A hostname is not a network address, but Services listen on
// multiple addresses (the IPv4 and IPv6 virtual IPs), and there's
// no clear winner here between the two. Therefore prefer the FQDN.
//
// In the case of TCP or HTTP Services, the port will be added below.
addr: fqdn,
}
if m, ok := mode.(serviceModeWithPort); ok {
if m.port() == 0 {
return nil, errors.New("must specify a port to advertise")
}
svcAddr.addr += ":" + strconv.Itoa(int(m.port()))
}
// Start listening on a local TCP socket.
ln, err := net.Listen("tcp", "localhost:0")
if err != nil {
return nil, fmt.Errorf("starting local listener: %w", err)
}
switch m := mode.(type) {
case ServiceModeTCP:
// Forward all connections from service-hostname:port to our socket.
srvConfig.SetTCPForwardingForService(
m.Port, ln.Addr().String(), m.TerminateTLS,
tailcfg.ServiceName(svcName), m.PROXYProtocolVersion, st.CurrentTailnet.MagicDNSSuffix)
case ServiceModeHTTP:
// For HTTP Services, proxy all connections to our socket.
mds := st.CurrentTailnet.MagicDNSSuffix
haveRootHandler := false
// We need to add a separate proxy for each mount point in the caps map.
for path, caps := range m.capsMap() {
if !strings.HasPrefix(path, "/") {
path = "/" + path
}
h := ipn.HTTPHandler{
AcceptAppCaps: caps,
Proxy: ln.Addr().String(),
}
if path == "/" {
haveRootHandler = true
} else {
h.Proxy += path
}
srvConfig.SetWebHandler(&h, svcName, m.Port, path, m.HTTPS, mds)
}
// We always need a root handler.
if !haveRootHandler {
h := ipn.HTTPHandler{Proxy: ln.Addr().String()}
srvConfig.SetWebHandler(&h, svcName, m.Port, "/", m.HTTPS, mds)
}
default:
ln.Close()
return nil, fmt.Errorf("unknown ServiceMode type %T", m)
}
if err := s.lb.SetServeConfig(srvConfig, srvConfigETag); err != nil {
ln.Close()
return nil, err
}
// TODO(hwh33,tailscale/corp#35860): clean up state (advertising prefs,
// serve config changes) when the returned listener is closed.
return &ServiceListener{
Listener: ln,
FQDN: fqdn,
addr: svcAddr,
}, nil
}
type listenOn string
@@ -1282,6 +1626,12 @@ func (s *Server) listen(network, addr string, lnOn listenOn) (net.Listener, erro
return ln, nil
}
// GetRootPath returns the root path of the tsnet server.
// This is where the state file and other data is stored.
func (s *Server) GetRootPath() string {
return s.rootPath
}
// CapturePcap can be called by the application code compiled with tsnet to save a pcap
// of packets which the netstack within tsnet sees. This is expected to be useful during
// debugging, probably not useful for production.
@@ -1343,7 +1693,12 @@ func (ln *listener) Accept() (net.Conn, error) {
}
}
func (ln *listener) Addr() net.Addr { return addr{ln} }
func (ln *listener) Addr() net.Addr {
return addr{
network: ln.keys[0].network,
addr: ln.addr,
}
}
func (ln *listener) Close() error {
ln.s.mu.Lock()
@@ -1383,7 +1738,26 @@ func (ln *listener) handle(c net.Conn) {
// Server returns the tsnet Server associated with the listener.
func (ln *listener) Server() *Server { return ln.s }
type addr struct{ ln *listener }
type addr struct {
network, addr string
}
func (a addr) Network() string { return a.ln.keys[0].network }
func (a addr) String() string { return a.ln.addr }
func (a addr) Network() string { return a.network }
func (a addr) String() string { return a.addr }
// cleanupListener wraps a net.Listener with a function to be run on Close.
type cleanupListener struct {
net.Listener
cleanupOnce sync.Once
cleanup func() error // nil if unused
}
func (cl *cleanupListener) Close() error {
var cleanupErr error
cl.cleanupOnce.Do(func() {
if cl.cleanup != nil {
cleanupErr = cl.cleanup()
}
})
return errors.Join(cl.Listener.Close(), cleanupErr)
}