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

Fixes #1339

Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
David Anderson 2021-03-02 19:32:04 -08:00
parent b4cf837d8a
commit 8d77dfdacb
2 changed files with 23 additions and 1 deletions

View File

@ -71,6 +71,17 @@ func Tailscale4To6Range() netaddr.IPPrefix {
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
// given Tailscale IPv4 address. Returns a zero IP if ipv4 isn't a
// Tailscale IPv4 address.

View File

@ -21,6 +21,7 @@ import (
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
"tailscale.com/net/interfaces"
"tailscale.com/net/tsaddr"
"tailscale.com/wgengine/winnet"
)
@ -305,7 +306,17 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) {
foundDefault4 := false
foundDefault6 := false
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")
}