Compare commits

...

1 Commits

Author SHA1 Message Date
James Tucker
8d5551528d cmd/tailscale,ipn,types/preftype,wgengine/router: introduce netfilter modes representing new capabilities
These are not yet plumbed to work, and are not yet documented in the CLI
help output. If accepted they would take the place of the debug flags,
and provide a persistent way for users to explicitly switch firewall
modes between the integrations that we support (currently iptables and
nftables).

Signed-off-by: James Tucker <james@tailscale.com>
2023-08-25 15:56:15 -07:00
7 changed files with 98 additions and 64 deletions

View File

@@ -84,7 +84,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
WantRunning: false,
Hostname: "foo",
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
AllowSingleHosts: true,
},
want: accidentalUpPrefix + " --accept-dns --hostname=foo",
@@ -95,7 +95,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
AllowSingleHosts: true,
Hostname: "foo",
},
@@ -107,7 +107,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
AllowSingleHosts: true,
Hostname: "foo",
},
@@ -129,7 +129,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
OperatorUser: "alice",
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
curUser: "eve",
want: accidentalUpPrefix + " --hostname=foo --operator=alice",
@@ -141,7 +141,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
OperatorUser: "alice",
},
curUser: "alice",
@@ -154,7 +154,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("10.0.42.0/24"),
netip.MustParsePrefix("0.0.0.0/0"),
@@ -170,7 +170,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("10.0.42.0/24"),
netip.MustParsePrefix("0.0.0.0/0"),
@@ -186,7 +186,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("10.0.42.0/24"),
netip.MustParsePrefix("0.0.0.0/0"),
@@ -202,7 +202,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
want: "",
},
@@ -213,7 +213,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("1.2.0.0/16"),
@@ -228,7 +228,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("0.0.0.0/0"),
netip.MustParsePrefix("::/0"),
@@ -244,7 +244,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
ExitNodeID: "fooID",
},
@@ -269,7 +269,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
netip.MustParsePrefix("0.0.0.0/0"),
netip.MustParsePrefix("::/0"),
},
NetfilterMode: preftype.NetfilterNoDivert,
NetfilterMode: preftype.NetfilterIPTablesNoDivert,
OperatorUser: "alice",
},
curUser: "eve",
@@ -292,7 +292,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("10.0.0.0/16"),
},
NetfilterMode: preftype.NetfilterNoDivert,
NetfilterMode: preftype.NetfilterIPTablesNoDivert,
OperatorUser: "alice",
},
curUser: "eve",
@@ -306,7 +306,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
LoggedOut: true,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
want: "", // not an error. LoggedOut is implicit.
},
@@ -334,7 +334,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
NetfilterMode: preftype.NetfilterNoDivert, // we never had this bug, but pretend it got set non-zero on Windows somehow
NetfilterMode: preftype.NetfilterIPTablesNoDivert, // we never had this bug, but pretend it got set non-zero on Windows somehow
},
goos: "openbsd",
want: "", // not an error
@@ -346,7 +346,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("0.0.0.0/0"),
netip.MustParsePrefix("::/0"),
@@ -362,7 +362,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
AdvertiseRoutes: []netip.Prefix{
netip.MustParsePrefix("0.0.0.0/0"),
netip.MustParsePrefix("::/0"),
@@ -378,7 +378,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
WantRunning: false,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
AllowSingleHosts: true,
Hostname: "foo",
@@ -392,7 +392,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
ExitNodeIP: netip.MustParseAddr("100.64.5.4"),
},
@@ -406,7 +406,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
ExitNodeID: "some_stable_id",
},
@@ -420,7 +420,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
ExitNodeAllowLANAccess: true,
ExitNodeID: "some_stable_id",
@@ -434,7 +434,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: "https://login.tailscale.com",
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
want: "", // not an error
},
@@ -445,7 +445,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: "https://login.tailscale.com",
AllowSingleHosts: true,
CorpDNS: false,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
want: accidentalUpPrefix + " --netfilter-mode=off --accept-dns=false",
},
@@ -459,7 +459,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
CorpDNS: true,
AllowSingleHosts: true,
RouteAll: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
goos: "linux",
distro: distro.Synology,
@@ -475,7 +475,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
CorpDNS: true,
AllowSingleHosts: true,
RouteAll: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
goos: "linux",
distro: "", // not Synology
@@ -488,7 +488,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) {
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
AllowSingleHosts: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
ProfileName: "foo",
},
goos: "linux",
@@ -552,7 +552,7 @@ func TestPrefsFromUpArgs(t *testing.T) {
ControlURL: ipn.DefaultControlURL,
WantRunning: true,
NoSNAT: false,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
CorpDNS: true,
AllowSingleHosts: true,
},
@@ -567,7 +567,7 @@ func TestPrefsFromUpArgs(t *testing.T) {
CorpDNS: true,
AllowSingleHosts: true,
RouteAll: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
},
{
@@ -582,7 +582,7 @@ func TestPrefsFromUpArgs(t *testing.T) {
netip.MustParsePrefix("0.0.0.0/0"),
netip.MustParsePrefix("::/0"),
},
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
},
{
@@ -667,7 +667,7 @@ func TestPrefsFromUpArgs(t *testing.T) {
wantWarn: "netfilter=nodivert; add iptables calls to ts-* chains manually.",
want: &ipn.Prefs{
WantRunning: true,
NetfilterMode: preftype.NetfilterNoDivert,
NetfilterMode: preftype.NetfilterIPTablesNoDivert,
NoSNAT: true,
},
},
@@ -899,7 +899,7 @@ func TestUpdatePrefs(t *testing.T) {
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
env: upCheckEnv{backendState: "Running"},
wantSimpleUp: true,
@@ -914,7 +914,7 @@ func TestUpdatePrefs(t *testing.T) {
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
env: upCheckEnv{backendState: "Running"},
},
@@ -926,7 +926,7 @@ func TestUpdatePrefs(t *testing.T) {
ControlURL: "https://login.tailscale.com",
CorpDNS: true,
AllowSingleHosts: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
OperatorUser: "somebody",
},
env: upCheckEnv{user: "somebody", backendState: "Running"},
@@ -948,7 +948,7 @@ func TestUpdatePrefs(t *testing.T) {
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
RunSSHSet: true,
@@ -970,7 +970,7 @@ func TestUpdatePrefs(t *testing.T) {
AllowSingleHosts: true,
CorpDNS: true,
RunSSH: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
RunSSHSet: true,
@@ -994,7 +994,7 @@ func TestUpdatePrefs(t *testing.T) {
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
RunSSH: true,
},
wantJustEditMP: &ipn.MaskedPrefs{
@@ -1018,7 +1018,7 @@ func TestUpdatePrefs(t *testing.T) {
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
RunSSHSet: true,
@@ -1041,7 +1041,7 @@ func TestUpdatePrefs(t *testing.T) {
Persist: &persist.Persist{UserProfile: tailcfg.UserProfile{LoginName: "crawshaw.github"}},
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
RunSSHSet: true,
@@ -1064,7 +1064,7 @@ func TestUpdatePrefs(t *testing.T) {
AllowSingleHosts: true,
CorpDNS: true,
RunSSH: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
RunSSHSet: true,
@@ -1085,7 +1085,7 @@ func TestUpdatePrefs(t *testing.T) {
ControlURL: "https://login.tailscale.com",
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
env: upCheckEnv{backendState: "Running"},
wantErrSubtr: "aborted, no changes made",
@@ -1098,7 +1098,7 @@ func TestUpdatePrefs(t *testing.T) {
ControlURL: "https://login.tailscale.com",
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
},
wantJustEditMP: nil,
env: upCheckEnv{backendState: "Running"},

View File

@@ -286,14 +286,36 @@ func prefsFromUpArgs(upArgs upArgsT, warnf logger.Logf, st *ipnstate.Status, goo
switch upArgs.netfilterMode {
case "on":
prefs.NetfilterMode = preftype.NetfilterOn
case "nodivert":
prefs.NetfilterMode = preftype.NetfilterNoDivert
switch distro.Get() {
case distro.Gokrazy:
prefs.NetfilterMode = preftype.NetfilterNFTablesOn
default:
// Historically "on" always mapped to iptables, so that is
// retained here. In a future version the default may switch
// from "on" to "auto", but this default should likely remain to
// avoid changing the behavior for existing users who pass the
// flag.
prefs.NetfilterMode = preftype.NetfilterIPTablesOn
}
case "iptables":
prefs.NetfilterMode = preftype.NetfilterIPTablesOn
case "nodivert", "iptables-nodivert":
prefs.NetfilterMode = preftype.NetfilterIPTablesNoDivert
warnf("netfilter=nodivert; add iptables calls to ts-* chains manually.")
case "auto":
prefs.NetfilterMode = preftype.NetfilterAutoOn
case "auto-nodivert":
prefs.NetfilterMode = preftype.NetfilterAutoNoDivert
warnf("netfilter=auto-nodivert; add iptables/nftables calls to ts-* chains manually.")
case "nftables":
prefs.NetfilterMode = preftype.NetfilterNFTablesOn
case "nftables-nodivert":
prefs.NetfilterMode = preftype.NetfilterNFTablesNoDivert
warnf("netfilter=nftables-nodivert; add nftables calls to ts-* chains manually.")
case "off":
prefs.NetfilterMode = preftype.NetfilterOff
if defaultNetfilterMode() != "off" {
warnf("netfilter=off; configure iptables yourself.")
warnf("netfilter=off; configure firewall filters yourself.")
}
default:
return nil, fmt.Errorf("invalid value --netfilter-mode=%q", upArgs.netfilterMode)
@@ -818,7 +840,7 @@ func checkForAccidentalSettingReverts(newPrefs, curPrefs *ipn.Prefs, env upCheck
// Issue 3176. Old prefs had 'RouteAll: true' on disk, so ignore that.
continue
}
if flagName == "netfilter-mode" && valNew == preftype.NetfilterOn && env.goos == "linux" && env.distro == distro.Synology {
if flagName == "netfilter-mode" && valNew == preftype.NetfilterIPTablesOn && env.goos == "linux" && env.distro == distro.Synology {
// Issue 6811. Ignore on Synology.
continue
}

View File

@@ -458,7 +458,7 @@ func NewPrefs() *Prefs {
AllowSingleHosts: true,
CorpDNS: true,
WantRunning: false,
NetfilterMode: preftype.NetfilterOn,
NetfilterMode: preftype.NetfilterIPTablesOn,
}
}

View File

@@ -253,12 +253,12 @@ func TestPrefsEqual(t *testing.T) {
{
&Prefs{NetfilterMode: preftype.NetfilterOff},
&Prefs{NetfilterMode: preftype.NetfilterOn},
&Prefs{NetfilterMode: preftype.NetfilterIPTablesOn},
false,
},
{
&Prefs{NetfilterMode: preftype.NetfilterOn},
&Prefs{NetfilterMode: preftype.NetfilterOn},
&Prefs{NetfilterMode: preftype.NetfilterIPTablesOn},
&Prefs{NetfilterMode: preftype.NetfilterIPTablesOn},
true,
},
@@ -639,7 +639,7 @@ func TestMaskedPrefsPretty(t *testing.T) {
RouteAll: false,
ExitNodeID: "foo",
AdvertiseTags: []string{"tag:foo", "tag:bar"},
NetfilterMode: preftype.NetfilterNoDivert,
NetfilterMode: preftype.NetfilterIPTablesNoDivert,
},
RouteAllSet: true,
HostnameSet: true,

View File

@@ -12,19 +12,31 @@ type NetfilterMode int
// These numbers are persisted to disk in JSON files and thus can't be
// renumbered or repurposed.
const (
NetfilterOff NetfilterMode = 0 // remove all tailscale netfilter state
NetfilterNoDivert NetfilterMode = 1 // manage tailscale chains, but don't call them
NetfilterOn NetfilterMode = 2 // manage tailscale chains and call them from main chains
NetfilterOff NetfilterMode = 0 // remove all tailscale netfilter state
NetfilterIPTablesNoDivert NetfilterMode = 1 // manage tailscale IPTables chains, but don't call them
NetfilterIPTablesOn NetfilterMode = 2 // manage tailscale IPTables chains and call them from main chains
NetfilterNFTablesNoDivert NetfilterMode = 3 // manage tailscale nftables chains, but don't call them
NetfilterNFTablesOn NetfilterMode = 4 // manage tailscale nftables chains and call them from conventional tables
NetfilterAutoNoDivert NetfilterMode = 5 // manage chains in the mode that best fits the system, but don't call them
NetfilterAutoOn NetfilterMode = 6 // manage chains in the mode that best fits the system, and call them from the main/conventional chains
)
func (m NetfilterMode) String() string {
switch m {
case NetfilterOff:
return "off"
case NetfilterNoDivert:
return "nodivert"
case NetfilterOn:
return "on"
case NetfilterIPTablesNoDivert:
return "nodivert(iptables)"
case NetfilterIPTablesOn:
return "on(iptables)"
case NetfilterNFTablesNoDivert:
return "nodivert(nftables)"
case NetfilterNFTablesOn:
return "on(nftables)"
case NetfilterAutoNoDivert:
return "nodivert(auto)"
case NetfilterAutoOn:
return "on(auto)"
default:
return "???"
}

View File

@@ -33,8 +33,8 @@ import (
const (
netfilterOff = preftype.NetfilterOff
netfilterNoDivert = preftype.NetfilterNoDivert
netfilterOn = preftype.NetfilterOn
netfilterNoDivert = preftype.NetfilterIPTablesNoDivert
netfilterOn = preftype.NetfilterIPTablesOn
)
// netfilterRunner abstracts helpers to run netfilter commands. It is

View File

@@ -126,12 +126,12 @@ func TestConfigEqual(t *testing.T) {
{
&Config{NetfilterMode: preftype.NetfilterOff},
&Config{NetfilterMode: preftype.NetfilterNoDivert},
&Config{NetfilterMode: preftype.NetfilterIPTablesNoDivert},
false,
},
{
&Config{NetfilterMode: preftype.NetfilterNoDivert},
&Config{NetfilterMode: preftype.NetfilterNoDivert},
&Config{NetfilterMode: preftype.NetfilterIPTablesNoDivert},
&Config{NetfilterMode: preftype.NetfilterIPTablesNoDivert},
true,
},
{