summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@tailscale.com>2021-11-19 11:17:03 -0800
committerBrad Fitzpatrick <bradfitz@tailscale.com>2021-11-22 08:48:59 -0800
commitc65466225004e11e7e94b826f013ddbbe9a5e898 (patch)
tree30d8f7a4e8d6e4bc990a9dfdc2e2c76a7fab4891
parentbcb979f8bf2ce59eb99d4cf5c5a6780b8a4ac0b9 (diff)
downloadtailscale-bradfitz/1.18.1.tar.xz
tailscale-bradfitz/1.18.1.zip
wgengine/router: fix checkIPRuleSupportsV6 to actually use IPv6bradfitz/1.18.1
Updates #3358 (should fix it) Updates #391 Change-Id: Ia62437dfa81247b0b5994d554cf279c3d540e4e7 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> (cherry picked from commit 946dfec98a365029e20fbcde00e327c3ccebd186)
-rw-r--r--wgengine/router/router_linux.go23
-rw-r--r--wgengine/router/router_linux_test.go2
2 files changed, 19 insertions, 6 deletions
diff --git a/wgengine/router/router_linux.go b/wgengine/router/router_linux.go
index 593975878..79d11b7c6 100644
--- a/wgengine/router/router_linux.go
+++ b/wgengine/router/router_linux.go
@@ -119,7 +119,7 @@ func newUserspaceRouter(logf logger.Logf, tunDev tun.Device, linkMon *monitor.Mo
return nil, err
}
- v6err := checkIPv6()
+ v6err := checkIPv6(logf)
if v6err != nil {
logf("disabling tunneled IPv6 due to system IPv6 config: %v", v6err)
}
@@ -169,7 +169,7 @@ func newUserspaceRouterAdvanced(logf logger.Logf, tunname string, linkMon *monit
r.logf("error querying IP rules (does kernel have IP_MULTIPLE_TABLES?): %v", err)
r.logf("warning: running without policy routing")
} else {
- r.logf("policy routing available; found %d rules", len(rules))
+ r.logf("[v1] policy routing available; found %d rules", len(rules))
r.ipRuleAvailable = true
}
}
@@ -1492,7 +1492,7 @@ func cleanup(logf logger.Logf, interfaceName string) {
// missing. It does not check that IPv6 is currently functional or
// that there's a global address, just that the system would support
// IPv6 if it were on an IPv6 network.
-func checkIPv6() error {
+func checkIPv6(logf logger.Logf) error {
_, err := os.Stat("/proc/sys/net/ipv6")
if os.IsNotExist(err) {
return err
@@ -1524,7 +1524,7 @@ func checkIPv6() error {
}
}
- if err := checkIPRuleSupportsV6(); err != nil {
+ if err := checkIPRuleSupportsV6(logf); err != nil {
return fmt.Errorf("kernel doesn't support IPv6 policy routing: %w", err)
}
@@ -1552,11 +1552,24 @@ func supportsV6NAT() bool {
return bytes.Contains(bs, []byte("nat\n"))
}
-func checkIPRuleSupportsV6() error {
+func checkIPRuleSupportsV6(logf logger.Logf) error {
+ // First try just a read-only operation to ideally avoid
+ // having to modify any state.
+ if rules, err := netlink.RuleList(netlink.FAMILY_V6); err != nil {
+ return fmt.Errorf("querying IPv6 policy routing rules: %w", err)
+ } else {
+ if len(rules) > 0 {
+ logf("[v1] kernel supports IPv6 policy routing (found %d rules)", len(rules))
+ return nil
+ }
+ }
+
+ // Try to actually create & delete one as a test.
rule := netlink.NewRule()
rule.Priority = 1234
rule.Mark = tailscaleBypassMarkNum
rule.Table = tailscaleRouteTable.num
+ rule.Family = netlink.FAMILY_V6
// First delete the rule unconditionally, and don't check for
// errors. This is just cleaning up anything that might be already
// there.
diff --git a/wgengine/router/router_linux_test.go b/wgengine/router/router_linux_test.go
index 186be209f..32dca7937 100644
--- a/wgengine/router/router_linux_test.go
+++ b/wgengine/router/router_linux_test.go
@@ -803,7 +803,7 @@ func TestDebugListRules(t *testing.T) {
}
func TestCheckIPRuleSupportsV6(t *testing.T) {
- err := checkIPRuleSupportsV6()
+ err := checkIPRuleSupportsV6(t.Logf)
if err != nil && os.Getuid() != 0 {
t.Skipf("skipping, error when not root: %v", err)
}