diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index fd2f80681..6fc26a2b5 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -3670,6 +3670,17 @@ func betterAddr(a, b addrLatency) bool { if a.IsZero() { return false } + if a.IP.Is6() && b.IP.Is4() { + // Prefer IPv6 for being a bit more robust, as long as + // the latencies are roughly equivalent. + if a.latency/10*9 < b.latency { + return true + } + } else if a.IP.Is4() && b.IP.Is6() { + if betterAddr(b, a) { + return false + } + } return a.latency < b.latency } diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index a48676e30..bd3e3781e 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -1867,6 +1867,29 @@ func TestBetterAddr(t *testing.T) { {a: zero, b: al("10.0.0.2:123", 5*ms), want: false}, {a: al("10.0.0.2:123", 5*ms), b: al("1.2.3.4:555", 6*ms), want: true}, {a: al("10.0.0.2:123", 5*ms), b: al("10.0.0.2:123", 10*ms), want: false}, // same IPPort + + // Prefer IPv6 if roughly equivalent: + { + a: al("[2001::5]:123", 100*ms), + b: al("1.2.3.4:555", 91*ms), + want: true, + }, + { + a: al("1.2.3.4:555", 91*ms), + b: al("[2001::5]:123", 100*ms), + want: false, + }, + // But not if IPv4 is much faster: + { + a: al("[2001::5]:123", 100*ms), + b: al("1.2.3.4:555", 30*ms), + want: false, + }, + { + a: al("1.2.3.4:555", 30*ms), + b: al("[2001::5]:123", 100*ms), + want: true, + }, } for _, tt := range tests { got := betterAddr(tt.a, tt.b)