mirror of
https://github.com/tailscale/tailscale.git
synced 2025-10-28 05:00:08 +00:00
feature/portmapper: make the portmapper & its debugging tools modular
Starting at a minimal binary and adding one feature back...
tailscaled tailscale combined (linux/amd64)
30073135 17451704 31543692 omitting everything
+ 480302 + 10258 + 493896 .. add debugportmapper
+ 475317 + 151943 + 467660 .. add portmapper
+ 500086 + 162873 + 510511 .. add portmapper+debugportmapper
Fixes #17148
Change-Id: I90bd0e9d1bd8cbe64fa2e885e9afef8fb5ee74b1
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
2b0f59cd38
commit
99b3f69126
@@ -798,7 +798,9 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
||||
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/ipn/ipnlocal+
|
||||
tailscale.com/feature/buildfeatures from tailscale.com/wgengine/magicsock+
|
||||
tailscale.com/feature/condregister/portmapper from tailscale.com/tsnet
|
||||
tailscale.com/feature/portmapper from tailscale.com/feature/condregister/portmapper
|
||||
tailscale.com/feature/syspolicy from tailscale.com/logpolicy
|
||||
tailscale.com/health from tailscale.com/control/controlclient+
|
||||
tailscale.com/health/healthmsg from tailscale.com/ipn/ipnlocal+
|
||||
@@ -866,7 +868,8 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
||||
tailscale.com/net/packet from tailscale.com/net/connstats+
|
||||
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/ipn/localapi+
|
||||
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/routetable from tailscale.com/doctor/routetable
|
||||
💣 tailscale.com/net/sockopts from tailscale.com/wgengine/magicsock
|
||||
|
||||
@@ -22,9 +22,9 @@ import (
|
||||
|
||||
var (
|
||||
cacheDir = flag.String("cachedir", "", "if non-empty, use this directory to store cached size results to speed up subsequent runs. The tool does not consider the git status when deciding whether to use the cache. It's on you to nuke it between runs if the tree changed.")
|
||||
features = flag.String("features", "", "comma-separated list of features to consider, with or without the ts_omit_ prefix")
|
||||
features = flag.String("features", "", "comma-separated list of features to list in the table, with or without the ts_omit_ prefix. It may also contain a '+' sign(s) for ANDing features together. If empty, all omittable features are considered one at a time.")
|
||||
|
||||
showRemovals = flag.Bool("show-removals", false, "if true, show a table of sizes removing one feature at a time from the full set")
|
||||
showRemovals = flag.Bool("show-removals", false, "if true, show a table of sizes removing one feature at a time from the full set.")
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -43,10 +43,14 @@ func main() {
|
||||
all = slices.Clone(allOmittable)
|
||||
} else {
|
||||
for v := range strings.SplitSeq(*features, ",") {
|
||||
if !strings.HasPrefix(v, "ts_omit_") {
|
||||
v = "ts_omit_" + v
|
||||
var withOmit []string
|
||||
for v := range strings.SplitSeq(v, "+") {
|
||||
if !strings.HasPrefix(v, "ts_omit_") {
|
||||
v = "ts_omit_" + v
|
||||
}
|
||||
withOmit = append(withOmit, v)
|
||||
}
|
||||
all = append(all, v)
|
||||
all = append(all, strings.Join(withOmit, "+"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +74,9 @@ func main() {
|
||||
fmt.Printf("-%8d -%8d -%8d omit-all\n", baseD-minD, baseC-minC, baseBoth-minBoth)
|
||||
|
||||
for _, t := range all {
|
||||
if strings.Contains(t, "+") {
|
||||
log.Fatalf("TODO: make --show-removals support ANDed features like %q", t)
|
||||
}
|
||||
sizeD := measure("tailscaled", t)
|
||||
sizeC := measure("tailscale", t)
|
||||
sizeBoth := measure("tailscaled", append([]string{t}, "ts_include_cli")...)
|
||||
@@ -84,17 +91,17 @@ func main() {
|
||||
fmt.Printf("%9s %9s %9s\n", "tailscaled", "tailscale", "combined (linux/amd64)")
|
||||
fmt.Printf("%9d %9d %9d omitting everything\n", minD, minC, minBoth)
|
||||
for _, t := range all {
|
||||
tags := allExcept(allOmittable, t)
|
||||
tags := allExcept(allOmittable, strings.Split(t, "+"))
|
||||
sizeD := measure("tailscaled", tags...)
|
||||
sizeC := measure("tailscale", tags...)
|
||||
sizeBoth := measure("tailscaled", append(tags, "ts_include_cli")...)
|
||||
fmt.Printf("+%8d +%8d +%8d .. add %s\n", max(sizeD-minD, 0), max(sizeC-minC, 0), max(sizeBoth-minBoth, 0), strings.TrimPrefix(t, "ts_omit_"))
|
||||
fmt.Printf("+%8d +%8d +%8d .. add %s\n", max(sizeD-minD, 0), max(sizeC-minC, 0), max(sizeBoth-minBoth, 0), strings.ReplaceAll(t, "ts_omit_", ""))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func allExcept(all []string, omit string) []string {
|
||||
return slices.DeleteFunc(slices.Clone(all), func(s string) bool { return s == omit })
|
||||
func allExcept(all, omit []string) []string {
|
||||
return slices.DeleteFunc(slices.Clone(all), func(s string) bool { return slices.Contains(omit, s) })
|
||||
}
|
||||
|
||||
func measure(bin string, tags ...string) int64 {
|
||||
|
||||
79
cmd/tailscale/cli/debug-portmap.go
Normal file
79
cmd/tailscale/cli/debug-portmap.go
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !ios && !ts_omit_debugportmapper
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/netip"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/peterbourgon/ff/v3/ffcli"
|
||||
"tailscale.com/client/local"
|
||||
)
|
||||
|
||||
func init() {
|
||||
debugPortmapCmd = mkDebugPortmapCmd
|
||||
}
|
||||
|
||||
func mkDebugPortmapCmd() *ffcli.Command {
|
||||
return &ffcli.Command{
|
||||
Name: "portmap",
|
||||
ShortUsage: "tailscale debug portmap",
|
||||
Exec: debugPortmap,
|
||||
ShortHelp: "Run portmap debugging",
|
||||
FlagSet: (func() *flag.FlagSet {
|
||||
fs := newFlagSet("portmap")
|
||||
fs.DurationVar(&debugPortmapArgs.duration, "duration", 5*time.Second, "timeout for port mapping")
|
||||
fs.StringVar(&debugPortmapArgs.ty, "type", "", `portmap debug type (one of "", "pmp", "pcp", or "upnp")`)
|
||||
fs.StringVar(&debugPortmapArgs.gatewayAddr, "gateway-addr", "", `override gateway IP (must also pass --self-addr)`)
|
||||
fs.StringVar(&debugPortmapArgs.selfAddr, "self-addr", "", `override self IP (must also pass --gateway-addr)`)
|
||||
fs.BoolVar(&debugPortmapArgs.logHTTP, "log-http", false, `print all HTTP requests and responses to the log`)
|
||||
return fs
|
||||
})(),
|
||||
}
|
||||
}
|
||||
|
||||
var debugPortmapArgs struct {
|
||||
duration time.Duration
|
||||
gatewayAddr string
|
||||
selfAddr string
|
||||
ty string
|
||||
logHTTP bool
|
||||
}
|
||||
|
||||
func debugPortmap(ctx context.Context, args []string) error {
|
||||
opts := &local.DebugPortmapOpts{
|
||||
Duration: debugPortmapArgs.duration,
|
||||
Type: debugPortmapArgs.ty,
|
||||
LogHTTP: debugPortmapArgs.logHTTP,
|
||||
}
|
||||
if (debugPortmapArgs.gatewayAddr != "") != (debugPortmapArgs.selfAddr != "") {
|
||||
return fmt.Errorf("if one of --gateway-addr and --self-addr is provided, the other must be as well")
|
||||
}
|
||||
if debugPortmapArgs.gatewayAddr != "" {
|
||||
var err error
|
||||
opts.GatewayAddr, err = netip.ParseAddr(debugPortmapArgs.gatewayAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid --gateway-addr: %w", err)
|
||||
}
|
||||
opts.SelfAddr, err = netip.ParseAddr(debugPortmapArgs.selfAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid --self-addr: %w", err)
|
||||
}
|
||||
}
|
||||
rc, err := localClient.DebugPortmap(ctx, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
_, err = io.Copy(os.Stdout, rc)
|
||||
return err
|
||||
}
|
||||
@@ -30,7 +30,6 @@ import (
|
||||
"github.com/peterbourgon/ff/v3/ffcli"
|
||||
"golang.org/x/net/http/httpproxy"
|
||||
"golang.org/x/net/http2"
|
||||
"tailscale.com/client/local"
|
||||
"tailscale.com/client/tailscale/apitype"
|
||||
"tailscale.com/control/controlhttp"
|
||||
"tailscale.com/hostinfo"
|
||||
@@ -50,6 +49,7 @@ import (
|
||||
|
||||
var (
|
||||
debugCaptureCmd func() *ffcli.Command // or nil
|
||||
debugPortmapCmd func() *ffcli.Command // or nil
|
||||
)
|
||||
|
||||
func debugCmd() *ffcli.Command {
|
||||
@@ -319,21 +319,7 @@ func debugCmd() *ffcli.Command {
|
||||
ShortHelp: "Test a DERP configuration",
|
||||
},
|
||||
ccall(debugCaptureCmd),
|
||||
{
|
||||
Name: "portmap",
|
||||
ShortUsage: "tailscale debug portmap",
|
||||
Exec: debugPortmap,
|
||||
ShortHelp: "Run portmap debugging",
|
||||
FlagSet: (func() *flag.FlagSet {
|
||||
fs := newFlagSet("portmap")
|
||||
fs.DurationVar(&debugPortmapArgs.duration, "duration", 5*time.Second, "timeout for port mapping")
|
||||
fs.StringVar(&debugPortmapArgs.ty, "type", "", `portmap debug type (one of "", "pmp", "pcp", or "upnp")`)
|
||||
fs.StringVar(&debugPortmapArgs.gatewayAddr, "gateway-addr", "", `override gateway IP (must also pass --self-addr)`)
|
||||
fs.StringVar(&debugPortmapArgs.selfAddr, "self-addr", "", `override self IP (must also pass --gateway-addr)`)
|
||||
fs.BoolVar(&debugPortmapArgs.logHTTP, "log-http", false, `print all HTTP requests and responses to the log`)
|
||||
return fs
|
||||
})(),
|
||||
},
|
||||
ccall(debugPortmapCmd),
|
||||
{
|
||||
Name: "peer-endpoint-changes",
|
||||
ShortUsage: "tailscale debug peer-endpoint-changes <hostname-or-IP>",
|
||||
@@ -1210,44 +1196,6 @@ func runSetExpire(ctx context.Context, args []string) error {
|
||||
return localClient.DebugSetExpireIn(ctx, setExpireArgs.in)
|
||||
}
|
||||
|
||||
var debugPortmapArgs struct {
|
||||
duration time.Duration
|
||||
gatewayAddr string
|
||||
selfAddr string
|
||||
ty string
|
||||
logHTTP bool
|
||||
}
|
||||
|
||||
func debugPortmap(ctx context.Context, args []string) error {
|
||||
opts := &local.DebugPortmapOpts{
|
||||
Duration: debugPortmapArgs.duration,
|
||||
Type: debugPortmapArgs.ty,
|
||||
LogHTTP: debugPortmapArgs.logHTTP,
|
||||
}
|
||||
if (debugPortmapArgs.gatewayAddr != "") != (debugPortmapArgs.selfAddr != "") {
|
||||
return fmt.Errorf("if one of --gateway-addr and --self-addr is provided, the other must be as well")
|
||||
}
|
||||
if debugPortmapArgs.gatewayAddr != "" {
|
||||
var err error
|
||||
opts.GatewayAddr, err = netip.ParseAddr(debugPortmapArgs.gatewayAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid --gateway-addr: %w", err)
|
||||
}
|
||||
opts.SelfAddr, err = netip.ParseAddr(debugPortmapArgs.selfAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid --self-addr: %w", err)
|
||||
}
|
||||
}
|
||||
rc, err := localClient.DebugPortmap(ctx, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
_, err = io.Copy(os.Stdout, rc)
|
||||
return err
|
||||
}
|
||||
|
||||
func runPeerEndpointChanges(ctx context.Context, args []string) error {
|
||||
st, err := localClient.Status(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -17,14 +17,23 @@ import (
|
||||
|
||||
"github.com/peterbourgon/ff/v3/ffcli"
|
||||
"tailscale.com/envknob"
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/ipn"
|
||||
"tailscale.com/net/netcheck"
|
||||
"tailscale.com/net/netmon"
|
||||
"tailscale.com/net/portmapper"
|
||||
"tailscale.com/net/portmapper/portmappertype"
|
||||
"tailscale.com/net/tlsdial"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/util/eventbus"
|
||||
|
||||
// The "netcheck" command also wants the portmapper linked.
|
||||
//
|
||||
// TODO: make that subcommand either hit LocalAPI for that info, or use a
|
||||
// tailscaled subcommand, to avoid making the CLI also link in the portmapper.
|
||||
// For now (2025-09-15), keep doing what we've done for the past five years and
|
||||
// keep linking it here.
|
||||
_ "tailscale.com/feature/condregister/portmapper"
|
||||
)
|
||||
|
||||
var netcheckCmd = &ffcli.Command{
|
||||
@@ -56,14 +65,13 @@ func runNetcheck(ctx context.Context, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure that we close the portmapper after running a netcheck; this
|
||||
// will release any port mappings created.
|
||||
pm := portmapper.NewClient(portmapper.Config{
|
||||
Logf: logf,
|
||||
NetMon: netMon,
|
||||
EventBus: bus,
|
||||
})
|
||||
defer pm.Close()
|
||||
var pm portmappertype.Client
|
||||
if buildfeatures.HasPortMapper {
|
||||
// Ensure that we close the portmapper after running a netcheck; this
|
||||
// will release any port mappings created.
|
||||
pm = portmappertype.HookNewPortMapper.Get()(logf, bus, netMon, nil, nil)
|
||||
defer pm.Close()
|
||||
}
|
||||
|
||||
c := &netcheck.Client{
|
||||
NetMon: netMon,
|
||||
@@ -210,6 +218,9 @@ func printReport(dm *tailcfg.DERPMap, report *netcheck.Report) error {
|
||||
}
|
||||
|
||||
func portMapping(r *netcheck.Report) string {
|
||||
if !buildfeatures.HasPortMapper {
|
||||
return "binary built without portmapper support"
|
||||
}
|
||||
if !r.AnyPortMappingChecked() {
|
||||
return "not checked"
|
||||
}
|
||||
|
||||
@@ -96,7 +96,6 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
||||
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
|
||||
tailscale.com/control/controlhttp from tailscale.com/cmd/tailscale/cli
|
||||
tailscale.com/control/controlhttp/controlhttpcommon from tailscale.com/control/controlhttp
|
||||
tailscale.com/control/controlknobs from tailscale.com/net/portmapper
|
||||
tailscale.com/derp from tailscale.com/derp/derphttp+
|
||||
tailscale.com/derp/derpconst from tailscale.com/derp+
|
||||
tailscale.com/derp/derphttp from tailscale.com/net/netcheck
|
||||
@@ -105,7 +104,10 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
||||
tailscale.com/envknob from tailscale.com/client/local+
|
||||
tailscale.com/envknob/featureknob from tailscale.com/client/web
|
||||
tailscale.com/feature from tailscale.com/tsweb+
|
||||
tailscale.com/feature/buildfeatures from tailscale.com/cmd/tailscale/cli
|
||||
tailscale.com/feature/capture/dissector from tailscale.com/cmd/tailscale/cli
|
||||
tailscale.com/feature/condregister/portmapper from tailscale.com/cmd/tailscale/cli
|
||||
tailscale.com/feature/portmapper from tailscale.com/feature/condregister/portmapper
|
||||
tailscale.com/feature/syspolicy from tailscale.com/cmd/tailscale/cli
|
||||
tailscale.com/health from tailscale.com/net/tlsdial+
|
||||
tailscale.com/health/healthmsg from tailscale.com/cmd/tailscale/cli
|
||||
@@ -131,7 +133,8 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
||||
tailscale.com/net/netutil from tailscale.com/client/local+
|
||||
tailscale.com/net/netx from tailscale.com/control/controlhttp+
|
||||
tailscale.com/net/ping from tailscale.com/net/netcheck
|
||||
tailscale.com/net/portmapper from tailscale.com/cmd/tailscale/cli+
|
||||
tailscale.com/net/portmapper from tailscale.com/feature/portmapper
|
||||
tailscale.com/net/portmapper/portmappertype from tailscale.com/net/netcheck+
|
||||
tailscale.com/net/sockstats from tailscale.com/control/controlhttp+
|
||||
tailscale.com/net/stun from tailscale.com/net/netcheck
|
||||
L tailscale.com/net/tcpinfo from tailscale.com/derp
|
||||
@@ -175,7 +178,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
||||
💣 tailscale.com/util/deephash from tailscale.com/util/syspolicy/setting
|
||||
L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics
|
||||
tailscale.com/util/dnsname from tailscale.com/cmd/tailscale/cli+
|
||||
tailscale.com/util/eventbus from tailscale.com/net/portmapper+
|
||||
tailscale.com/util/eventbus from tailscale.com/client/local+
|
||||
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/tailscale+
|
||||
@@ -351,7 +354,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
||||
encoding/hex from crypto/x509+
|
||||
encoding/json from expvar+
|
||||
encoding/pem from crypto/tls+
|
||||
encoding/xml from github.com/tailscale/goupnp+
|
||||
encoding/xml from github.com/godbus/dbus/v5/introspect+
|
||||
errors from archive/tar+
|
||||
expvar from tailscale.com/derp+
|
||||
flag from github.com/peterbourgon/ff/v3+
|
||||
|
||||
@@ -272,10 +272,13 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
||||
tailscale.com/envknob from tailscale.com/client/local+
|
||||
tailscale.com/envknob/featureknob from tailscale.com/client/web+
|
||||
tailscale.com/feature from tailscale.com/feature/wakeonlan+
|
||||
tailscale.com/feature/buildfeatures from tailscale.com/ipn/ipnlocal+
|
||||
tailscale.com/feature/buildfeatures from tailscale.com/wgengine/magicsock+
|
||||
tailscale.com/feature/capture from tailscale.com/feature/condregister
|
||||
tailscale.com/feature/condregister from tailscale.com/cmd/tailscaled
|
||||
tailscale.com/feature/condregister/portmapper from tailscale.com/feature/condregister
|
||||
tailscale.com/feature/debugportmapper from tailscale.com/feature/condregister
|
||||
tailscale.com/feature/drive from tailscale.com/feature/condregister
|
||||
tailscale.com/feature/portmapper from tailscale.com/feature/condregister/portmapper
|
||||
tailscale.com/feature/relayserver from tailscale.com/feature/condregister
|
||||
tailscale.com/feature/syspolicy from tailscale.com/feature/condregister+
|
||||
tailscale.com/feature/taildrop from tailscale.com/feature/condregister
|
||||
@@ -338,7 +341,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
||||
tailscale.com/net/packet from tailscale.com/net/connstats+
|
||||
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/ipn/localapi+
|
||||
tailscale.com/net/portmapper from tailscale.com/feature/portmapper+
|
||||
tailscale.com/net/portmapper/portmappertype from tailscale.com/feature/portmapper+
|
||||
tailscale.com/net/proxymux from tailscale.com/cmd/tailscaled
|
||||
tailscale.com/net/routetable from tailscale.com/doctor/routetable
|
||||
💣 tailscale.com/net/sockopts from tailscale.com/wgengine/magicsock+
|
||||
|
||||
@@ -90,3 +90,21 @@ func TestOmitTailnetLock(t *testing.T) {
|
||||
},
|
||||
}.Check(t)
|
||||
}
|
||||
|
||||
func TestOmitPortmapper(t *testing.T) {
|
||||
deptest.DepChecker{
|
||||
GOOS: "linux",
|
||||
GOARCH: "amd64",
|
||||
Tags: "ts_omit_portmapper,ts_include_cli,ts_omit_debugportmapper",
|
||||
OnDep: func(dep string) {
|
||||
if dep == "tailscale.com/net/portmapper" {
|
||||
t.Errorf("unexpected dep with ts_omit_portmapper: %q", dep)
|
||||
return
|
||||
}
|
||||
if strings.Contains(dep, "goupnp") || strings.Contains(dep, "/soap") ||
|
||||
strings.Contains(dep, "internetgateway2") {
|
||||
t.Errorf("unexpected dep with ts_omit_portmapper: %q", dep)
|
||||
}
|
||||
},
|
||||
}.Check(t)
|
||||
}
|
||||
|
||||
@@ -239,7 +239,9 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
||||
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/ipn/ipnlocal+
|
||||
tailscale.com/feature/buildfeatures from tailscale.com/wgengine/magicsock+
|
||||
tailscale.com/feature/condregister/portmapper from tailscale.com/tsnet
|
||||
tailscale.com/feature/portmapper from tailscale.com/feature/condregister/portmapper
|
||||
tailscale.com/feature/syspolicy from tailscale.com/logpolicy
|
||||
tailscale.com/health from tailscale.com/control/controlclient+
|
||||
tailscale.com/health/healthmsg from tailscale.com/ipn/ipnlocal+
|
||||
@@ -295,7 +297,8 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
||||
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/ipn/localapi+
|
||||
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/routetable from tailscale.com/doctor/routetable
|
||||
💣 tailscale.com/net/sockopts from tailscale.com/wgengine/magicsock
|
||||
|
||||
Reference in New Issue
Block a user