diff --git a/wgengine/wgcfg/config.go b/wgengine/wgcfg/config.go index 154dc0a30..86adb34d0 100644 --- a/wgengine/wgcfg/config.go +++ b/wgengine/wgcfg/config.go @@ -21,6 +21,7 @@ type Config struct { NodeID tailcfg.StableNodeID PrivateKey key.NodePrivate Addresses []netip.Prefix + ListenPort uint16 // not used by Tailscale's conn.Bind implementation MTU uint16 DNS []netip.Addr Peers []Peer diff --git a/wgengine/wgcfg/parser.go b/wgengine/wgcfg/parser.go index ec3d008f7..397f37af8 100644 --- a/wgengine/wgcfg/parser.go +++ b/wgengine/wgcfg/parser.go @@ -124,7 +124,13 @@ func (cfg *Config) handleDeviceLine(k, value mem.RO, valueBytes []byte) error { if err != nil { return err } - case k.EqualString("listen_port") || k.EqualString("fwmark"): + case k.EqualString("listen_port"): + port, err := mem.ParseUint(value, 10, 16) + if err != nil { + return fmt.Errorf("failed to parse listen_port: %w", err) + } + cfg.ListenPort = uint16(port) + case k.EqualString("fwmark"): // ignore default: return fmt.Errorf("unexpected IpcGetOperation key: %q", k.StringCopy()) diff --git a/wgengine/wgcfg/wgcfg_clone.go b/wgengine/wgcfg/wgcfg_clone.go index 749d8d816..cf0419860 100644 --- a/wgengine/wgcfg/wgcfg_clone.go +++ b/wgengine/wgcfg/wgcfg_clone.go @@ -39,6 +39,7 @@ var _ConfigCloneNeedsRegeneration = Config(struct { NodeID tailcfg.StableNodeID PrivateKey key.NodePrivate Addresses []netip.Prefix + ListenPort uint16 MTU uint16 DNS []netip.Addr Peers []Peer diff --git a/wgengine/wgcfg/writer.go b/wgengine/wgcfg/writer.go index 9cdd31df2..df79e0ad6 100644 --- a/wgengine/wgcfg/writer.go +++ b/wgengine/wgcfg/writer.go @@ -42,6 +42,9 @@ func (cfg *Config) ToUAPI(logf logger.Logf, w io.Writer, prev *Config) error { if !prev.PrivateKey.Equal(cfg.PrivateKey) { set("private_key", cfg.PrivateKey.UntypedHexString()) } + if prev.ListenPort != cfg.ListenPort { + setUint16("listen_port", cfg.ListenPort) + } old := make(map[key.NodePublic]Peer) for _, p := range prev.Peers {