Bläddra i källkod

wgengine/router: add a dummy IPv6 address if needed for default routing.

Fixes #1339

Signed-off-by: David Anderson <[email protected]>
David Anderson 5 år sedan
förälder
incheckning
8d77dfdacb
2 ändrade filer med 23 tillägg och 1 borttagningar
  1. 11 0
      net/tsaddr/tsaddr.go
  2. 12 1
      wgengine/router/ifconfig_windows.go

+ 11 - 0
net/tsaddr/tsaddr.go

@@ -71,6 +71,17 @@ func Tailscale4To6Range() netaddr.IPPrefix {
 	return ula4To6Range.v
 	return ula4To6Range.v
 }
 }
 
 
+// Tailscale4To6Placeholder returns an IP address that can be used as
+// a source IP when one is required, but a netmap didn't provide
+// any. This address never gets allocated by the 4-to-6 algorithm in
+// control.
+//
+// Currently used to work around a Windows limitation when programming
+// IPv6 routes in corner cases.
+func Tailscale4To6Placeholder() netaddr.IP {
+	return Tailscale4To6Range().IP
+}
+
 // Tailscale4To6 returns a Tailscale IPv6 address that maps 1:1 to the
 // Tailscale4To6 returns a Tailscale IPv6 address that maps 1:1 to the
 // given Tailscale IPv4 address. Returns a zero IP if ipv4 isn't a
 // given Tailscale IPv4 address. Returns a zero IP if ipv4 isn't a
 // Tailscale IPv4 address.
 // Tailscale IPv4 address.

+ 12 - 1
wgengine/router/ifconfig_windows.go

@@ -21,6 +21,7 @@ import (
 	"golang.org/x/sys/windows"
 	"golang.org/x/sys/windows"
 	"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
 	"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
 	"tailscale.com/net/interfaces"
 	"tailscale.com/net/interfaces"
+	"tailscale.com/net/tsaddr"
 	"tailscale.com/wgengine/winnet"
 	"tailscale.com/wgengine/winnet"
 )
 )
 
 
@@ -305,7 +306,17 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) {
 	foundDefault4 := false
 	foundDefault4 := false
 	foundDefault6 := false
 	foundDefault6 := false
 	for _, route := range cfg.Routes {
 	for _, route := range cfg.Routes {
-		if (route.IP.Is4() && firstGateway4 == nil) || (route.IP.Is6() && firstGateway6 == nil) {
+		if route.IP.Is6() && firstGateway6 == nil {
+			// Windows won't let us set IPv6 routes without having an
+			// IPv6 local address set. However, when we've configured
+			// a default route, we want to forcibly grab IPv6 traffic
+			// even if the v6 overlay network isn't configured. To do
+			// that, we add a dummy local IPv6 address to serve as a
+			// route source.
+			ipnet := &net.IPNet{tsaddr.Tailscale4To6Placeholder().IPAddr().IP, net.CIDRMask(128, 128)}
+			addresses = append(addresses, ipnet)
+			firstGateway6 = &ipnet.IP
+		} else if route.IP.Is4() && firstGateway4 == nil {
 			return errors.New("Due to a Windows limitation, one cannot have interface routes without an interface address")
 			return errors.New("Due to a Windows limitation, one cannot have interface routes without an interface address")
 		}
 		}