ipn,wgengine: remove vestigial Prefs.AllowSingleHosts

It was requested by the first customer 4-5 years ago and only used
for a brief moment of time. We later added netmap visibility trimming
which removes the need for this.

It's been hidden by the CLI for quite some time and never documented
anywhere else.

This keeps the CLI flag, though, out of caution. It just returns an
error if it's set to anything but true (its default).

Fixes #12058

Change-Id: I7514ba572e7b82519b04ed603ff9f3bdbaecfda7
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/12181/head
Brad Fitzpatrick 3 weeks ago committed by Brad Fitzpatrick
parent 1384c24e41
commit 964282d34f

@ -186,12 +186,11 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "losing_hostname",
flags: []string{"--accept-dns"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
WantRunning: false,
Hostname: "foo",
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AllowSingleHosts: true,
ControlURL: ipn.DefaultControlURL,
WantRunning: false,
Hostname: "foo",
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
want: accidentalUpPrefix + " --accept-dns --hostname=foo",
},
@ -199,11 +198,10 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "hostname_changing_explicitly",
flags: []string{"--hostname=bar"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AllowSingleHosts: true,
Hostname: "foo",
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
Hostname: "foo",
},
want: "",
},
@ -211,11 +209,10 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "hostname_changing_empty_explicitly",
flags: []string{"--hostname="},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AllowSingleHosts: true,
Hostname: "foo",
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
Hostname: "foo",
},
want: "",
},
@ -231,11 +228,10 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "implicit_operator_change",
flags: []string{"--hostname=foo"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
OperatorUser: "alice",
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
OperatorUser: "alice",
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
curUser: "eve",
want: accidentalUpPrefix + " --hostname=foo --operator=alice",
@ -244,11 +240,10 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "implicit_operator_matches_shell_user",
flags: []string{"--hostname=foo"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
OperatorUser: "alice",
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
OperatorUser: "alice",
},
curUser: "alice",
want: "",
@ -257,10 +252,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "error_advertised_routes_exit_node_removed",
flags: []string{"--advertise-routes=10.0.42.0/24"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("10.0.42.0/24"),
netip.MustParsePrefix("0.0.0.0/0"),
@ -273,10 +267,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "advertised_routes_exit_node_removed_explicit",
flags: []string{"--advertise-routes=10.0.42.0/24", "--advertise-exit-node=false"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("10.0.42.0/24"),
netip.MustParsePrefix("0.0.0.0/0"),
@ -289,10 +282,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "advertised_routes_includes_the_0_routes", // but no --advertise-exit-node
flags: []string{"--advertise-routes=11.1.43.0/24,0.0.0.0/0,::/0"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("10.0.42.0/24"),
netip.MustParsePrefix("0.0.0.0/0"),
@ -305,10 +297,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "advertise_exit_node", // Issue 1859
flags: []string{"--advertise-exit-node"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
want: "",
},
@ -316,10 +307,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "advertise_exit_node_over_existing_routes",
flags: []string{"--advertise-exit-node"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("1.2.0.0/16"),
@ -331,10 +321,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "advertise_exit_node_over_existing_routes_and_exit_node",
flags: []string{"--advertise-exit-node"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("0.0.0.0/0"),
netip.MustParsePrefix("::/0"),
@ -347,10 +336,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "exit_node_clearing", // Issue 1777
flags: []string{"--exit-node="},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ExitNodeID: "fooID",
},
@ -360,16 +348,15 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "remove_all_implicit",
flags: []string{"--force-reauth"},
curPrefs: &ipn.Prefs{
WantRunning: true,
ControlURL: ipn.DefaultControlURL,
RouteAll: true,
AllowSingleHosts: false,
ExitNodeIP: netip.MustParseAddr("100.64.5.6"),
CorpDNS: false,
ShieldsUp: true,
AdvertiseTags: []string{"tag:foo", "tag:bar"},
Hostname: "myhostname",
ForceDaemon: true,
WantRunning: true,
ControlURL: ipn.DefaultControlURL,
RouteAll: true,
ExitNodeIP: netip.MustParseAddr("100.64.5.6"),
CorpDNS: false,
ShieldsUp: true,
AdvertiseTags: []string{"tag:foo", "tag:bar"},
Hostname: "myhostname",
ForceDaemon: true,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("10.0.0.0/16"),
netip.MustParsePrefix("0.0.0.0/0"),
@ -379,22 +366,21 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
OperatorUser: "alice",
},
curUser: "eve",
want: accidentalUpPrefix + " --force-reauth --accept-dns=false --accept-routes --advertise-exit-node --advertise-routes=10.0.0.0/16 --advertise-tags=tag:foo,tag:bar --exit-node=100.64.5.6 --host-routes=false --hostname=myhostname --netfilter-mode=nodivert --operator=alice --shields-up",
want: accidentalUpPrefix + " --force-reauth --accept-dns=false --accept-routes --advertise-exit-node --advertise-routes=10.0.0.0/16 --advertise-tags=tag:foo,tag:bar --exit-node=100.64.5.6 --hostname=myhostname --netfilter-mode=nodivert --operator=alice --shields-up",
},
{
name: "remove_all_implicit_except_hostname",
flags: []string{"--hostname=newhostname"},
curPrefs: &ipn.Prefs{
WantRunning: true,
ControlURL: ipn.DefaultControlURL,
RouteAll: true,
AllowSingleHosts: false,
ExitNodeIP: netip.MustParseAddr("100.64.5.6"),
CorpDNS: false,
ShieldsUp: true,
AdvertiseTags: []string{"tag:foo", "tag:bar"},
Hostname: "myhostname",
ForceDaemon: true,
WantRunning: true,
ControlURL: ipn.DefaultControlURL,
RouteAll: true,
ExitNodeIP: netip.MustParseAddr("100.64.5.6"),
CorpDNS: false,
ShieldsUp: true,
AdvertiseTags: []string{"tag:foo", "tag:bar"},
Hostname: "myhostname",
ForceDaemon: true,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("10.0.0.0/16"),
},
@ -402,17 +388,16 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
OperatorUser: "alice",
},
curUser: "eve",
want: accidentalUpPrefix + " --hostname=newhostname --accept-dns=false --accept-routes --advertise-routes=10.0.0.0/16 --advertise-tags=tag:foo,tag:bar --exit-node=100.64.5.6 --host-routes=false --netfilter-mode=nodivert --operator=alice --shields-up",
want: accidentalUpPrefix + " --hostname=newhostname --accept-dns=false --accept-routes --advertise-routes=10.0.0.0/16 --advertise-tags=tag:foo,tag:bar --exit-node=100.64.5.6 --netfilter-mode=nodivert --operator=alice --shields-up",
},
{
name: "loggedout_is_implicit",
flags: []string{"--hostname=foo"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
LoggedOut: true,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
LoggedOut: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
want: "", // not an error. LoggedOut is implicit.
},
@ -422,10 +407,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "make_windows_exit_node",
flags: []string{"--advertise-exit-node"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
RouteAll: true,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
RouteAll: true,
// And assume this no-op accidental pre-1.8 value:
NoSNAT: true,
@ -437,8 +421,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "ignore_netfilter_change_non_linux",
flags: []string{"--accept-dns"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
ControlURL: ipn.DefaultControlURL,
NetfilterMode: preftype.NetfilterNoDivert, // we never had this bug, but pretend it got set non-zero on Windows somehow
},
@ -449,10 +432,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "operator_losing_routes_step1", // https://twitter.com/EXPbits/status/1390418145047887877
flags: []string{"--operator=expbits"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("0.0.0.0/0"),
netip.MustParsePrefix("::/0"),
@ -465,10 +447,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "operator_losing_routes_step2", // https://twitter.com/EXPbits/status/1390418145047887877
flags: []string{"--operator=expbits", "--advertise-routes=1.2.0.0/16"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("0.0.0.0/0"),
netip.MustParsePrefix("::/0"),
@ -481,11 +462,10 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "errors_preserve_explicit_flags",
flags: []string{"--reset", "--force-reauth=false", "--authkey=secretrand"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
WantRunning: false,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AllowSingleHosts: true,
ControlURL: ipn.DefaultControlURL,
WantRunning: false,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
Hostname: "foo",
},
@ -495,10 +475,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "error_exit_node_omit_with_ip_pref",
flags: []string{"--hostname=foo"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ExitNodeIP: netip.MustParseAddr("100.64.5.4"),
},
@ -509,10 +488,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
flags: []string{"--hostname=foo"},
curExitNodeIP: netip.MustParseAddr("100.64.5.7"),
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ExitNodeID: "some_stable_id",
},
@ -523,10 +501,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
flags: []string{"--hostname=foo"},
curExitNodeIP: netip.MustParseAddr("100.2.3.4"),
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ExitNodeAllowLANAccess: true,
ExitNodeID: "some_stable_id",
@ -537,10 +514,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "ignore_login_server_synonym",
flags: []string{"--login-server=https://controlplane.tailscale.com"},
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
want: "", // not an error
},
@ -548,10 +524,9 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "ignore_login_server_synonym_on_other_change",
flags: []string{"--netfilter-mode=off"},
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
AllowSingleHosts: true,
CorpDNS: false,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
CorpDNS: false,
NetfilterMode: preftype.NetfilterOn,
},
want: accidentalUpPrefix + " --netfilter-mode=off --accept-dns=false",
},
@ -561,11 +536,10 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "synology_permit_omit_accept_routes",
flags: []string{"--hostname=foo"},
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
AllowSingleHosts: true,
RouteAll: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
RouteAll: true,
NetfilterMode: preftype.NetfilterOn,
},
goos: "linux",
distro: distro.Synology,
@ -577,11 +551,10 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "not_synology_dont_permit_omit_accept_routes",
flags: []string{"--hostname=foo"},
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
AllowSingleHosts: true,
RouteAll: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
RouteAll: true,
NetfilterMode: preftype.NetfilterOn,
},
goos: "linux",
distro: "", // not Synology
@ -591,11 +564,10 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
name: "profile_name_ignored_in_up",
flags: []string{"--hostname=foo"},
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
AllowSingleHosts: true,
NetfilterMode: preftype.NetfilterOn,
ProfileName: "foo",
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ProfileName: "foo",
},
goos: "linux",
want: "",
@ -661,7 +633,6 @@ func TestPrefsFromUpArgs(t *testing.T) {
NoStatefulFiltering: "false",
NetfilterMode: preftype.NetfilterOn,
CorpDNS: true,
AllowSingleHosts: true,
AutoUpdate: ipn.AutoUpdatePrefs{
Check: true,
},
@ -675,7 +646,6 @@ func TestPrefsFromUpArgs(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
WantRunning: true,
CorpDNS: true,
AllowSingleHosts: true,
RouteAll: true,
NoSNAT: false,
NoStatefulFiltering: "false",
@ -689,10 +659,9 @@ func TestPrefsFromUpArgs(t *testing.T) {
name: "advertise_default_route",
args: upArgsFromOSArgs("linux", "--advertise-exit-node"),
want: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
WantRunning: true,
AllowSingleHosts: true,
CorpDNS: true,
ControlURL: ipn.DefaultControlURL,
WantRunning: true,
CorpDNS: true,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("0.0.0.0/0"),
netip.MustParsePrefix("::/0"),
@ -922,6 +891,9 @@ func TestPrefFlagMapping(t *testing.T) {
continue
}
switch prefName {
case "AllowSingleHosts":
// Fake pref for downgrade compat. See #12058.
continue
case "WantRunning", "Persist", "LoggedOut":
// All explicitly handled (ignored) by checkForAccidentalSettingReverts.
continue
@ -1029,7 +1001,6 @@ func TestUpdatePrefs(t *testing.T) {
wantJustEditMP: &ipn.MaskedPrefs{
AdvertiseRoutesSet: true,
AdvertiseTagsSet: true,
AllowSingleHostsSet: true,
AppConnectorSet: true,
ControlURLSet: true,
CorpDNSSet: true,
@ -1062,11 +1033,10 @@ func TestUpdatePrefs(t *testing.T) {
name: "change_login_server",
flags: []string{"--login-server=https://localhost:1000"},
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
env: upCheckEnv{backendState: "Running"},
wantSimpleUp: true,
@ -1077,11 +1047,10 @@ func TestUpdatePrefs(t *testing.T) {
name: "change_tags",
flags: []string{"--advertise-tags=tag:foo"},
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
env: upCheckEnv{backendState: "Running"},
},
@ -1090,11 +1059,10 @@ func TestUpdatePrefs(t *testing.T) {
name: "explicit_empty_operator",
flags: []string{"--operator="},
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
AllowSingleHosts: true,
NetfilterMode: preftype.NetfilterOn,
OperatorUser: "somebody",
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
OperatorUser: "somebody",
},
env: upCheckEnv{user: "somebody", backendState: "Running"},
wantJustEditMP: &ipn.MaskedPrefs{
@ -1111,11 +1079,10 @@ func TestUpdatePrefs(t *testing.T) {
name: "enable_ssh",
flags: []string{"--ssh"},
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
RunSSHSet: true,
@ -1132,12 +1099,11 @@ func TestUpdatePrefs(t *testing.T) {
name: "disable_ssh",
flags: []string{"--ssh=false"},
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
RunSSH: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
CorpDNS: true,
RunSSH: true,
NetfilterMode: preftype.NetfilterOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
RunSSHSet: true,
@ -1157,12 +1123,11 @@ func TestUpdatePrefs(t *testing.T) {
flags: []string{"--ssh=false"},
sshOverTailscale: true,
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
RunSSH: true,
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
RunSSH: true,
},
wantJustEditMP: &ipn.MaskedPrefs{
RunSSHSet: true,
@ -1181,11 +1146,10 @@ func TestUpdatePrefs(t *testing.T) {
flags: []string{"--ssh=true"},
sshOverTailscale: true,
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
RunSSHSet: true,
@ -1204,11 +1168,10 @@ func TestUpdatePrefs(t *testing.T) {
flags: []string{"--ssh=true", "--accept-risk=lose-ssh"},
sshOverTailscale: true,
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
RunSSHSet: true,
@ -1226,12 +1189,11 @@ func TestUpdatePrefs(t *testing.T) {
flags: []string{"--ssh=false", "--accept-risk=lose-ssh"},
sshOverTailscale: true,
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
RunSSH: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
CorpDNS: true,
RunSSH: true,
NetfilterMode: preftype.NetfilterOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
RunSSHSet: true,
@ -1249,10 +1211,9 @@ func TestUpdatePrefs(t *testing.T) {
flags: []string{"--force-reauth"},
sshOverTailscale: true,
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
env: upCheckEnv{backendState: "Running"},
wantErrSubtr: "aborted, no changes made",
@ -1262,10 +1223,9 @@ func TestUpdatePrefs(t *testing.T) {
flags: []string{"--force-reauth", "--accept-risk=lose-ssh"},
sshOverTailscale: true,
curPrefs: &ipn.Prefs{
ControlURL: "https://login.tailscale.com",
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
wantJustEditMP: nil,
env: upCheckEnv{backendState: "Running"},
@ -1274,10 +1234,9 @@ func TestUpdatePrefs(t *testing.T) {
name: "advertise_connector",
flags: []string{"--advertise-connector"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
AppConnectorSet: true,
@ -1294,10 +1253,9 @@ func TestUpdatePrefs(t *testing.T) {
name: "no_advertise_connector",
flags: []string{"--advertise-connector=false"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AppConnector: ipn.AppConnectorPrefs{
Advertise: true,
},

@ -104,7 +104,7 @@ func newUpFlagSet(goos string, upArgs *upArgsT, cmd string) *flag.FlagSet {
upf.StringVar(&upArgs.server, "login-server", ipn.DefaultControlURL, "base URL of control server")
upf.BoolVar(&upArgs.acceptRoutes, "accept-routes", acceptRouteDefault(goos), "accept routes advertised by other Tailscale nodes")
upf.BoolVar(&upArgs.acceptDNS, "accept-dns", true, "accept DNS configuration from the admin panel")
upf.BoolVar(&upArgs.singleRoutes, "host-routes", true, hidden+"install host routes to other Tailscale nodes")
upf.Var(notFalseVar{}, "host-routes", hidden+"install host routes to other Tailscale nodes (must be true as of Tailscale 1.67+)")
upf.StringVar(&upArgs.exitNodeIP, "exit-node", "", "Tailscale exit node (IP or base name) for internet traffic, or empty string to not use an exit node")
upf.BoolVar(&upArgs.exitNodeAllowLANAccess, "exit-node-allow-lan-access", false, "Allow direct access to the local network when routing traffic via an exit node")
upf.BoolVar(&upArgs.shieldsUp, "shields-up", false, "don't allow incoming connections")
@ -143,6 +143,18 @@ func newUpFlagSet(goos string, upArgs *upArgsT, cmd string) *flag.FlagSet {
return upf
}
// notFalseVar is is a flag.Value that can only be "true", if set.
type notFalseVar struct{}
func (notFalseVar) IsBoolFlag() bool { return true }
func (notFalseVar) Set(v string) error {
if v != "true" {
return fmt.Errorf("unsupported value; only 'true' is allowed")
}
return nil
}
func (notFalseVar) String() string { return "true" }
func defaultNetfilterMode() string {
if distro.Get() == distro.Synology {
return "off"
@ -156,7 +168,6 @@ type upArgsT struct {
server string
acceptRoutes bool
acceptDNS bool
singleRoutes bool
exitNodeIP string
exitNodeAllowLANAccess bool
shieldsUp bool
@ -278,7 +289,6 @@ func prefsFromUpArgs(upArgs upArgsT, warnf logger.Logf, st *ipnstate.Status, goo
prefs.ExitNodeAllowLANAccess = upArgs.exitNodeAllowLANAccess
prefs.CorpDNS = upArgs.acceptDNS
prefs.AllowSingleHosts = upArgs.singleRoutes
prefs.ShieldsUp = upArgs.shieldsUp
prefs.RunSSH = upArgs.runSSH
prefs.RunWebClient = upArgs.runWebClient
@ -740,7 +750,6 @@ func init() {
addPrefFlagMapping("accept-dns", "CorpDNS")
addPrefFlagMapping("accept-routes", "RouteAll")
addPrefFlagMapping("advertise-tags", "AdvertiseTags")
addPrefFlagMapping("host-routes", "AllowSingleHosts")
addPrefFlagMapping("hostname", "Hostname")
addPrefFlagMapping("login-server", "ControlURL")
addPrefFlagMapping("netfilter-mode", "NetfilterMode")
@ -779,7 +788,7 @@ func addPrefFlagMapping(flagName string, prefNames ...string) {
// correspond to an ipn.Pref.
func preflessFlag(flagName string) bool {
switch flagName {
case "auth-key", "force-reauth", "reset", "qr", "json", "timeout", "accept-risk":
case "auth-key", "force-reauth", "reset", "qr", "json", "timeout", "accept-risk", "host-routes":
return true
}
return false
@ -975,8 +984,6 @@ func prefsToFlags(env upCheckEnv, prefs *ipn.Prefs) (flagVal map[string]any) {
set(prefs.ControlURL)
case "accept-routes":
set(prefs.RouteAll)
case "host-routes":
set(prefs.AllowSingleHosts)
case "accept-dns":
set(prefs.CorpDNS)
case "shields-up":

@ -298,11 +298,10 @@ func (i *jsIPN) run(jsCallbacks js.Value) {
go func() {
err := i.lb.Start(ipn.Options{
UpdatePrefs: &ipn.Prefs{
ControlURL: i.controlURL,
RouteAll: false,
AllowSingleHosts: true,
WantRunning: true,
Hostname: i.hostname,
ControlURL: i.controlURL,
RouteAll: false,
WantRunning: true,
Hostname: i.hostname,
},
AuthKey: i.authKey,
})

@ -40,7 +40,6 @@ func (src *Prefs) Clone() *Prefs {
var _PrefsCloneNeedsRegeneration = Prefs(struct {
ControlURL string
RouteAll bool
AllowSingleHosts bool
ExitNodeID tailcfg.StableNodeID
ExitNodeIP netip.Addr
InternalExitNodePrior tailcfg.StableNodeID
@ -67,6 +66,7 @@ var _PrefsCloneNeedsRegeneration = Prefs(struct {
PostureChecking bool
NetfilterKind string
DriveShares []*drive.Share
AllowSingleHosts marshalAsTrueInJSON
Persist *persist.Persist
}{})

@ -67,7 +67,6 @@ func (v *PrefsView) UnmarshalJSON(b []byte) error {
func (v PrefsView) ControlURL() string { return v.ж.ControlURL }
func (v PrefsView) RouteAll() bool { return v.ж.RouteAll }
func (v PrefsView) AllowSingleHosts() bool { return v.ж.AllowSingleHosts }
func (v PrefsView) ExitNodeID() tailcfg.StableNodeID { return v.ж.ExitNodeID }
func (v PrefsView) ExitNodeIP() netip.Addr { return v.ж.ExitNodeIP }
func (v PrefsView) InternalExitNodePrior() tailcfg.StableNodeID { return v.ж.InternalExitNodePrior }
@ -98,13 +97,13 @@ func (v PrefsView) NetfilterKind() string { return v.ж.Netfilte
func (v PrefsView) DriveShares() views.SliceView[*drive.Share, drive.ShareView] {
return views.SliceOfViews[*drive.Share, drive.ShareView](v.ж.DriveShares)
}
func (v PrefsView) Persist() persist.PersistView { return v.ж.Persist.View() }
func (v PrefsView) AllowSingleHosts() marshalAsTrueInJSON { return v.ж.AllowSingleHosts }
func (v PrefsView) Persist() persist.PersistView { return v.ж.Persist.View() }
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _PrefsViewNeedsRegeneration = Prefs(struct {
ControlURL string
RouteAll bool
AllowSingleHosts bool
ExitNodeID tailcfg.StableNodeID
ExitNodeIP netip.Addr
InternalExitNodePrior tailcfg.StableNodeID
@ -131,6 +130,7 @@ var _PrefsViewNeedsRegeneration = Prefs(struct {
PostureChecking bool
NetfilterKind string
DriveShares []*drive.Share
AllowSingleHosts marshalAsTrueInJSON
Persist *persist.Persist
}{})

@ -3649,9 +3649,6 @@ func (b *LocalBackend) authReconfig() {
if prefs.RouteAll() {
flags |= netmap.AllowSubnetRoutes
}
if prefs.AllowSingleHosts() {
flags |= netmap.AllowSingleHosts
}
if hasPAC && disableSubnetsIfPAC {
if flags&netmap.AllowSubnetRoutes != 0 {
b.logf("authReconfig: have PAC; disabling subnet routes")

@ -75,18 +75,6 @@ type Prefs struct {
// controlled by ExitNodeID/IP below.
RouteAll bool
// AllowSingleHosts specifies whether to install routes for each
// node IP on the tailscale network, in addition to a route for
// the whole network.
// This corresponds to the "tailscale up --host-routes" value,
// which defaults to true.
//
// TODO(danderson): why do we have this? It dumps a lot of stuff
// into the routing table, and a single network route _should_ be
// all that we need. But when I turn this off in my tailscaled,
// packets stop flowing. What's up with that?
AllowSingleHosts bool
// ExitNodeID and ExitNodeIP specify the node that should be used
// as an exit node for internet traffic. At most one of these
// should be non-zero.
@ -252,6 +240,16 @@ type Prefs struct {
// by name.
DriveShares []*drive.Share
// AllowSingleHosts was a legacy field that was always true
// for the past 4.5 years. It controlled whether Tailscale
// peers got /32 or /127 routes for each other.
// As of 2024-05-17 we're starting to ignore it, but to let
// people still downgrade Tailscale versions and not break
// all peer-to-peer networking we still write it to disk (as JSON)
// so it can be loaded back by old versions.
// TODO(bradfitz): delete this in 2025 sometime. See #12058.
AllowSingleHosts marshalAsTrueInJSON
// The Persist field is named 'Config' in the file for backward
// compatibility with earlier versions.
// TODO(apenwarr): We should move this out of here, it's not a pref.
@ -282,6 +280,13 @@ func (au1 AutoUpdatePrefs) Equals(au2 AutoUpdatePrefs) bool {
ok1 == ok2
}
type marshalAsTrueInJSON struct{}
var trueJSON = []byte("true")
func (marshalAsTrueInJSON) MarshalJSON() ([]byte, error) { return trueJSON, nil }
func (*marshalAsTrueInJSON) UnmarshalJSON([]byte) error { return nil }
// AppConnectorPrefs are the app connector settings for the node agent.
type AppConnectorPrefs struct {
// Advertise specifies whether the app connector subsystem is advertising
@ -299,7 +304,6 @@ type MaskedPrefs struct {
ControlURLSet bool `json:",omitempty"`
RouteAllSet bool `json:",omitempty"`
AllowSingleHostsSet bool `json:",omitempty"`
ExitNodeIDSet bool `json:",omitempty"`
ExitNodeIPSet bool `json:",omitempty"`
InternalExitNodePriorSet bool `json:",omitempty"` // Internal; can't be set by LocalAPI clients
@ -484,9 +488,6 @@ func (p *Prefs) pretty(goos string) string {
var sb strings.Builder
sb.WriteString("Prefs{")
fmt.Fprintf(&sb, "ra=%v ", p.RouteAll)
if !p.AllowSingleHosts {
sb.WriteString("mesh=false ")
}
fmt.Fprintf(&sb, "dns=%v want=%v ", p.CorpDNS, p.WantRunning)
if p.RunSSH {
sb.WriteString("ssh=true ")
@ -579,7 +580,6 @@ func (p *Prefs) Equals(p2 *Prefs) bool {
return p.ControlURL == p2.ControlURL &&
p.RouteAll == p2.RouteAll &&
p.AllowSingleHosts == p2.AllowSingleHosts &&
p.ExitNodeID == p2.ExitNodeID &&
p.ExitNodeIP == p2.ExitNodeIP &&
p.InternalExitNodePrior == p2.InternalExitNodePrior &&
@ -663,7 +663,6 @@ func NewPrefs() *Prefs {
ControlURL: "",
RouteAll: true,
AllowSingleHosts: true,
CorpDNS: true,
WantRunning: false,
NetfilterMode: preftype.NetfilterOn,

@ -38,7 +38,6 @@ func TestPrefsEqual(t *testing.T) {
prefsHandles := []string{
"ControlURL",
"RouteAll",
"AllowSingleHosts",
"ExitNodeID",
"ExitNodeIP",
"InternalExitNodePrior",
@ -65,6 +64,7 @@ func TestPrefsEqual(t *testing.T) {
"PostureChecking",
"NetfilterKind",
"DriveShares",
"AllowSingleHosts",
"Persist",
}
if have := fieldsOf(reflect.TypeFor[Prefs]()); !reflect.DeepEqual(have, prefsHandles) {
@ -123,18 +123,6 @@ func TestPrefsEqual(t *testing.T) {
&Prefs{RouteAll: true},
true,
},
{
&Prefs{AllowSingleHosts: true},
&Prefs{AllowSingleHosts: false},
false,
},
{
&Prefs{AllowSingleHosts: true},
&Prefs{AllowSingleHosts: true},
true,
},
{
&Prefs{ExitNodeID: "n1234"},
&Prefs{},
@ -376,7 +364,7 @@ func checkPrefs(t *testing.T, p Prefs) {
p2b = new(Prefs)
err = PrefsFromBytes(p2.ToBytes(), p2b)
if err != nil {
t.Fatalf("PrefsFromBytes(p2) failed\n")
t.Fatalf("PrefsFromBytes(p2) failed: bytes=%q; err=%v\n", p2.ToBytes(), err)
}
p2p := p2.Pretty()
p2bp := p2b.Pretty()
@ -427,46 +415,43 @@ func TestPrefsPretty(t *testing.T) {
{
Prefs{},
"linux",
"Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off update=off Persist=nil}",
"Prefs{ra=false dns=false want=false routes=[] nf=off update=off Persist=nil}",
},
{
Prefs{},
"windows",
"Prefs{ra=false mesh=false dns=false want=false update=off Persist=nil}",
"Prefs{ra=false dns=false want=false update=off Persist=nil}",
},
{
Prefs{ShieldsUp: true},
"windows",
"Prefs{ra=false mesh=false dns=false want=false shields=true update=off Persist=nil}",
"Prefs{ra=false dns=false want=false shields=true update=off Persist=nil}",
},
{
Prefs{AllowSingleHosts: true},
Prefs{},
"windows",
"Prefs{ra=false dns=false want=false update=off Persist=nil}",
},
{
Prefs{
NotepadURLs: true,
AllowSingleHosts: true,
NotepadURLs: true,
},
"windows",
"Prefs{ra=false dns=false want=false notepad=true update=off Persist=nil}",
},
{
Prefs{
AllowSingleHosts: true,
WantRunning: true,
ForceDaemon: true, // server mode
WantRunning: true,
ForceDaemon: true, // server mode
},
"windows",
"Prefs{ra=false dns=false want=true server=true update=off Persist=nil}",
},
{
Prefs{
AllowSingleHosts: true,
WantRunning: true,
ControlURL: "http://localhost:1234",
AdvertiseTags: []string{"tag:foo", "tag:bar"},
WantRunning: true,
ControlURL: "http://localhost:1234",
AdvertiseTags: []string{"tag:foo", "tag:bar"},
},
"darwin",
`Prefs{ra=false dns=false want=true tags=tag:foo,tag:bar url="http://localhost:1234" update=off Persist=nil}`,
@ -476,7 +461,7 @@ func TestPrefsPretty(t *testing.T) {
Persist: &persist.Persist{},
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off update=off Persist{lm=, o=, n= u=""}}`,
`Prefs{ra=false dns=false want=false routes=[] nf=off update=off Persist{lm=, o=, n= u=""}}`,
},
{
Prefs{
@ -485,21 +470,21 @@ func TestPrefsPretty(t *testing.T) {
},
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off update=off Persist{lm=, o=, n=[B1VKl] u=""}}`,
`Prefs{ra=false dns=false want=false routes=[] nf=off update=off Persist{lm=, o=, n=[B1VKl] u=""}}`,
},
{
Prefs{
ExitNodeIP: netip.MustParseAddr("1.2.3.4"),
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false exit=1.2.3.4 lan=false routes=[] nf=off update=off Persist=nil}`,
`Prefs{ra=false dns=false want=false exit=1.2.3.4 lan=false routes=[] nf=off update=off Persist=nil}`,
},
{
Prefs{
ExitNodeID: tailcfg.StableNodeID("myNodeABC"),
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false exit=myNodeABC lan=false routes=[] nf=off update=off Persist=nil}`,
`Prefs{ra=false dns=false want=false exit=myNodeABC lan=false routes=[] nf=off update=off Persist=nil}`,
},
{
Prefs{
@ -507,21 +492,21 @@ func TestPrefsPretty(t *testing.T) {
ExitNodeAllowLANAccess: true,
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false exit=myNodeABC lan=true routes=[] nf=off update=off Persist=nil}`,
`Prefs{ra=false dns=false want=false exit=myNodeABC lan=true routes=[] nf=off update=off Persist=nil}`,
},
{
Prefs{
ExitNodeAllowLANAccess: true,
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off update=off Persist=nil}`,
`Prefs{ra=false dns=false want=false routes=[] nf=off update=off Persist=nil}`,
},
{
Prefs{
Hostname: "foo",
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off host="foo" update=off Persist=nil}`,
`Prefs{ra=false dns=false want=false routes=[] nf=off host="foo" update=off Persist=nil}`,
},
{
Prefs{
@ -531,7 +516,7 @@ func TestPrefsPretty(t *testing.T) {
},
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off update=check Persist=nil}`,
`Prefs{ra=false dns=false want=false routes=[] nf=off update=check Persist=nil}`,
},
{
Prefs{
@ -541,7 +526,7 @@ func TestPrefsPretty(t *testing.T) {
},
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off update=on Persist=nil}`,
`Prefs{ra=false dns=false want=false routes=[] nf=off update=on Persist=nil}`,
},
{
Prefs{
@ -550,7 +535,7 @@ func TestPrefsPretty(t *testing.T) {
},
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off update=off appconnector=advertise Persist=nil}`,
`Prefs{ra=false dns=false want=false routes=[] nf=off update=off appconnector=advertise Persist=nil}`,
},
{
Prefs{
@ -559,21 +544,21 @@ func TestPrefsPretty(t *testing.T) {
},
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off update=off Persist=nil}`,
`Prefs{ra=false dns=false want=false routes=[] nf=off update=off Persist=nil}`,
},
{
Prefs{
NetfilterKind: "iptables",
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off netfilterKind=iptables update=off Persist=nil}`,
`Prefs{ra=false dns=false want=false routes=[] nf=off netfilterKind=iptables update=off Persist=nil}`,
},
{
Prefs{
NetfilterKind: "",
},
"linux",
`Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off update=off Persist=nil}`,
`Prefs{ra=false dns=false want=false routes=[] nf=off update=off Persist=nil}`,
},
}
for i, tt := range tests {
@ -633,8 +618,9 @@ func TestMaskedPrefsSetsInternal(t *testing.T) {
func TestMaskedPrefsFields(t *testing.T) {
have := map[string]bool{}
for _, f := range fieldsOf(reflect.TypeFor[Prefs]()) {
if f == "Persist" {
// This one can't be edited.
switch f {
case "Persist", "AllowSingleHosts":
// These can't be edited.
continue
}
have[f] = true
@ -753,13 +739,12 @@ func TestMaskedPrefsPretty(t *testing.T) {
{
m: &MaskedPrefs{
Prefs: Prefs{
Hostname: "bar",
OperatorUser: "galaxybrain",
AllowSingleHosts: true,
RouteAll: false,
ExitNodeID: "foo",
AdvertiseTags: []string{"tag:foo", "tag:bar"},
NetfilterMode: preftype.NetfilterNoDivert,
Hostname: "bar",
OperatorUser: "galaxybrain",
RouteAll: false,
ExitNodeID: "foo",
AdvertiseTags: []string{"tag:foo", "tag:bar"},
NetfilterMode: preftype.NetfilterNoDivert,
},
RouteAllSet: true,
HostnameSet: true,
@ -1064,3 +1049,24 @@ func TestNotifyPrefsJSONRoundtrip(t *testing.T) {
t.Fatal("Prefs should not be valid after deserialization")
}
}
// Verify that our Prefs type writes out an AllowSingleHosts field so we can
// downgrade to older versions that require it.
func TestPrefsDowngrade(t *testing.T) {
var p Prefs
j, err := json.Marshal(p)
if err != nil {
t.Fatal(err)
}
type oldPrefs struct {
AllowSingleHosts bool
}
var op oldPrefs
if err := json.Unmarshal(j, &op); err != nil {
t.Fatal(err)
}
if !op.AllowSingleHosts {
t.Fatal("AllowSingleHosts should be true")
}
}

@ -388,6 +388,6 @@ func (nm *NetworkMap) JSON() string {
type WGConfigFlags int
const (
AllowSingleHosts WGConfigFlags = 1 << iota
_ WGConfigFlags = 1 << iota
AllowSubnetRoutes
)

@ -331,7 +331,7 @@ func meshStacks(logf logger.Logf, mutateNetmap func(idx int, nm *netmap.NetworkM
peerSet.Add(peer.Key())
}
m.conn.UpdatePeers(peerSet)
wg, err := nmcfg.WGCfg(nm, logf, netmap.AllowSingleHosts, "")
wg, err := nmcfg.WGCfg(nm, logf, 0, "")
if err != nil {
// We're too far from the *testing.T to be graceful,
// blow up. Shouldn't happen anyway.
@ -2354,7 +2354,7 @@ func TestIsWireGuardOnlyPeer(t *testing.T) {
}
m.conn.SetNetworkMap(nm)
cfg, err := nmcfg.WGCfg(nm, t.Logf, netmap.AllowSingleHosts|netmap.AllowSubnetRoutes, "")
cfg, err := nmcfg.WGCfg(nm, t.Logf, netmap.AllowSubnetRoutes, "")
if err != nil {
t.Fatal(err)
}
@ -2416,7 +2416,7 @@ func TestIsWireGuardOnlyPeerWithMasquerade(t *testing.T) {
}
m.conn.SetNetworkMap(nm)
cfg, err := nmcfg.WGCfg(nm, t.Logf, netmap.AllowSingleHosts|netmap.AllowSubnetRoutes, "")
cfg, err := nmcfg.WGCfg(nm, t.Logf, netmap.AllowSubnetRoutes, "")
if err != nil {
t.Fatal(err)
}
@ -2456,7 +2456,7 @@ func applyNetworkMap(t *testing.T, m *magicStack, nm *netmap.NetworkMap) {
m.conn.noV6.Store(true)
// Turn the network map into a wireguard config (for the tailscale internal wireguard device).
cfg, err := nmcfg.WGCfg(nm, t.Logf, netmap.AllowSingleHosts|netmap.AllowSubnetRoutes, "")
cfg, err := nmcfg.WGCfg(nm, t.Logf, netmap.AllowSubnetRoutes, "")
if err != nil {
t.Fatal(err)
}

@ -10,7 +10,6 @@ import (
"net/netip"
"strings"
"tailscale.com/net/tsaddr"
"tailscale.com/tailcfg"
"tailscale.com/types/logger"
"tailscale.com/types/logid"
@ -124,12 +123,6 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags,
}
fmt.Fprintf(skippedUnselected, "%q (%v)", nodeDebugName(peer), peer.Key().ShortString())
continue
} else if allowedIP.IsSingleIP() && tsaddr.IsTailscaleIP(allowedIP.Addr()) && (flags&netmap.AllowSingleHosts) == 0 {
if skippedIPs.Len() > 0 {
skippedIPs.WriteString(", ")
}
fmt.Fprintf(skippedIPs, "%v from %q (%v)", allowedIP.Addr(), nodeDebugName(peer), peer.Key().ShortString())
continue
} else if cidrIsSubnet(peer, allowedIP) {
if (flags & netmap.AllowSubnetRoutes) == 0 {
if skippedSubnets.Len() > 0 {

Loading…
Cancel
Save