cmd/tailscale/cli: add ts2021 debug flag to set a dial plan

Updates tailscale/corp#32534

Change-Id: Ief4ee0a263ea1edbf652b74d8c335c1e5ee209d7
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2025-09-20 15:55:33 -07:00 committed by Brad Fitzpatrick
parent 798fddbe5c
commit d7ec043306

View File

@ -289,6 +289,7 @@ func debugCmd() *ffcli.Command {
fs.IntVar(&ts2021Args.version, "version", int(tailcfg.CurrentCapabilityVersion), "protocol version") fs.IntVar(&ts2021Args.version, "version", int(tailcfg.CurrentCapabilityVersion), "protocol version")
fs.BoolVar(&ts2021Args.verbose, "verbose", false, "be extra verbose") fs.BoolVar(&ts2021Args.verbose, "verbose", false, "be extra verbose")
fs.StringVar(&ts2021Args.aceHost, "ace", "", "if non-empty, use this ACE server IP/hostname as a candidate path") fs.StringVar(&ts2021Args.aceHost, "ace", "", "if non-empty, use this ACE server IP/hostname as a candidate path")
fs.StringVar(&ts2021Args.dialPlanJSONFile, "dial-plan", "", "if non-empty, use this JSON file to configure the dial plan")
return fs return fs
})(), })(),
}, },
@ -967,6 +968,8 @@ var ts2021Args struct {
version int // 27 or whatever version int // 27 or whatever
verbose bool verbose bool
aceHost string // if non-empty, FQDN of https ACE server to use ("ace.example.com") aceHost string // if non-empty, FQDN of https ACE server to use ("ace.example.com")
dialPlanJSONFile string // if non-empty, path to JSON file [tailcfg.ControlDialPlan] JSON
} }
func runTS2021(ctx context.Context, args []string) error { func runTS2021(ctx context.Context, args []string) error {
@ -1051,6 +1054,18 @@ func runTS2021(ctx context.Context, args []string) error {
return fmt.Errorf("creating netmon: %w", err) return fmt.Errorf("creating netmon: %w", err)
} }
var dialPlan *tailcfg.ControlDialPlan
if ts2021Args.dialPlanJSONFile != "" {
b, err := os.ReadFile(ts2021Args.dialPlanJSONFile)
if err != nil {
return fmt.Errorf("reading dial plan JSON file: %w", err)
}
dialPlan = new(tailcfg.ControlDialPlan)
if err := json.Unmarshal(b, dialPlan); err != nil {
return fmt.Errorf("unmarshaling dial plan JSON file: %w", err)
}
}
noiseDialer := &controlhttp.Dialer{ noiseDialer := &controlhttp.Dialer{
Hostname: ts2021Args.host, Hostname: ts2021Args.host,
HTTPPort: "80", HTTPPort: "80",
@ -1058,6 +1073,7 @@ func runTS2021(ctx context.Context, args []string) error {
MachineKey: machinePrivate, MachineKey: machinePrivate,
ControlKey: keys.PublicKey, ControlKey: keys.PublicKey,
ProtocolVersion: uint16(ts2021Args.version), ProtocolVersion: uint16(ts2021Args.version),
DialPlan: dialPlan,
Dialer: dialFunc, Dialer: dialFunc,
Logf: logf, Logf: logf,
NetMon: netMon, NetMon: netMon,