mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-18 02:48:40 +00:00
wgengine/router: probe better for v6 policy routing support.
Previously we disabled v6 support if the disable_policy knob was missing in /proc, but some kernels support policy routing without exposing the toggle. So instead, treat disable_policy absence as a "maybe", and make the direct `ip -6 rule` probing a bit more elaborate to compensate. Fixes #1241. Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
parent
717c715c96
commit
267531e4f8
@ -1045,18 +1045,22 @@ func checkIPv6() error {
|
||||
return errors.New("disable_ipv6 is set")
|
||||
}
|
||||
|
||||
// Older kernels don't support IPv6 policy routing.
|
||||
// Older kernels don't support IPv6 policy routing. Some kernels
|
||||
// support policy routing but don't have this knob, so absence of
|
||||
// the knob is not fatal.
|
||||
bs, err = ioutil.ReadFile("/proc/sys/net/ipv6/conf/all/disable_policy")
|
||||
if err != nil {
|
||||
// Absent knob means policy routing is unsupported.
|
||||
return err
|
||||
if err == nil {
|
||||
disabled, err = strconv.ParseBool(strings.TrimSpace(string(bs)))
|
||||
if err != nil {
|
||||
return errors.New("disable_policy has invalid bool")
|
||||
}
|
||||
if disabled {
|
||||
return errors.New("disable_policy is set")
|
||||
}
|
||||
}
|
||||
disabled, err = strconv.ParseBool(strings.TrimSpace(string(bs)))
|
||||
if err != nil {
|
||||
return errors.New("disable_policy has invalid bool")
|
||||
}
|
||||
if disabled {
|
||||
return errors.New("disable_policy is set")
|
||||
|
||||
if err := checkIPRuleSupportsV6(); err != nil {
|
||||
return fmt.Errorf("kernel doesn't support IPv6 policy routing: %w", err)
|
||||
}
|
||||
|
||||
// Some distros ship ip6tables separately from iptables.
|
||||
@ -1064,10 +1068,6 @@ func checkIPv6() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkIPRuleSupportsV6(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1088,13 +1088,17 @@ func supportsV6NAT() bool {
|
||||
}
|
||||
|
||||
func checkIPRuleSupportsV6() error {
|
||||
// First add a rule for "ip rule del" to delete.
|
||||
// We ignore the "add" operation's error because it can also
|
||||
// fail if the rule already exists.
|
||||
exec.Command("ip", "-6", "rule", "add",
|
||||
"pref", "123", "fwmark", tailscaleBypassMark, "table", fmt.Sprint(tailscaleRouteTable)).Run()
|
||||
out, err := exec.Command("ip", "-6", "rule", "del",
|
||||
"pref", "123", "fwmark", tailscaleBypassMark, "table", fmt.Sprint(tailscaleRouteTable)).CombinedOutput()
|
||||
add := []string{"-6", "rule", "add", "pref", "1234", "fwmark", tailscaleBypassMark, "table", tailscaleRouteTable}
|
||||
del := []string{"-6", "rule", "del", "pref", "1234", "fwmark", tailscaleBypassMark, "table", tailscaleRouteTable}
|
||||
|
||||
// First delete the rule unconditionally, and don't check for
|
||||
// errors. This is just cleaning up anything that might be already
|
||||
// there.
|
||||
exec.Command("ip", del...).Run()
|
||||
|
||||
// Try adding the rule. This will fail on systems that support
|
||||
// IPv6, but not IPv6 policy routing.
|
||||
out, err := exec.Command("ip", add...).CombinedOutput()
|
||||
if err != nil {
|
||||
out = bytes.TrimSpace(out)
|
||||
var detail interface{} = out
|
||||
@ -1103,5 +1107,8 @@ func checkIPRuleSupportsV6() error {
|
||||
}
|
||||
return fmt.Errorf("ip -6 rule failed: %s", detail)
|
||||
}
|
||||
|
||||
// Delete again.
|
||||
exec.Command("ip", del...).Run()
|
||||
return nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user