diff --git a/wgengine/magicsock/endpoint.go b/wgengine/magicsock/endpoint.go index 16036f638..2f8f1630e 100644 --- a/wgengine/magicsock/endpoint.go +++ b/wgengine/magicsock/endpoint.go @@ -1665,14 +1665,20 @@ func betterAddr(a, b addrQuality) bool { // pay for the bandwidth in a cloud environment. // // Additionally, prefer any loopback address strongly over non-loopback - // addresses. + // addresses, and prefer link-local unicast addresses over other types + // of private IP addresses since it's definitionally more likely that + // they'll be on the same network segment than a general private IP. if a.Addr().IsLoopback() { aPoints += 50 + } else if a.Addr().IsLinkLocalUnicast() { + aPoints += 30 } else if a.Addr().IsPrivate() { aPoints += 20 } if b.Addr().IsLoopback() { bPoints += 50 + } else if b.Addr().IsLinkLocalUnicast() { + bPoints += 30 } else if b.Addr().IsPrivate() { bPoints += 20 } diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index 640728d61..762ac7d57 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -1747,6 +1747,19 @@ func TestBetterAddr(t *testing.T) { b: al("192.168.0.1:555", 100*ms), want: false, }, + + // Link-local unicast addresses are preferred over other + // private IPs, but not as much as localhost addresses. + { + a: al("[fe80::ce8:474a:a27e:113b]:555", 101*ms), + b: al("[fd89:1a8a:8888:9999:aaaa:bbbb:cccc:dddd]:555", 100*ms), + want: true, + }, + { + a: al("[fe80::ce8:474a:a27e:113b]:555", 101*ms), + b: al("[::1]:555", 100*ms), + want: false, + }, } for i, tt := range tests { got := betterAddr(tt.a, tt.b)