mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-10-31 13:05:22 +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:
		 David Anderson
					David Anderson
				
			
				
					committed by
					
						 Dave Anderson
						Dave Anderson
					
				
			
			
				
	
			
			
			 Dave Anderson
						Dave Anderson
					
				
			
						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 | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user