wgengine/netstack: make SOCKS5 resolve names to IPv6 if self node when no IPv4
For instance, ephemeral nodes with only IPv6 addresses can now SOCKS5-dial out to names like "foo" and resolve foo's IPv6 address rather than foo's IPv4 address and get a "no route" (*tcpip.ErrNoRoute) error from netstack's dialer. Per https://github.com/tailscale/tailscale/issues/2268#issuecomment-870027626 which is only part of the isuse. Updates #2268 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>pull/2276/head
parent
1147c7fd4f
commit
722859b476
|
@ -177,21 +177,33 @@ type DNSMap map[string]netaddr.IP
|
||||||
func DNSMapFromNetworkMap(nm *netmap.NetworkMap) DNSMap {
|
func DNSMapFromNetworkMap(nm *netmap.NetworkMap) DNSMap {
|
||||||
ret := make(DNSMap)
|
ret := make(DNSMap)
|
||||||
suffix := nm.MagicDNSSuffix()
|
suffix := nm.MagicDNSSuffix()
|
||||||
|
have4 := false
|
||||||
if nm.Name != "" && len(nm.Addresses) > 0 {
|
if nm.Name != "" && len(nm.Addresses) > 0 {
|
||||||
ip := nm.Addresses[0].IP()
|
ip := nm.Addresses[0].IP()
|
||||||
ret[strings.TrimRight(nm.Name, ".")] = ip
|
ret[strings.TrimRight(nm.Name, ".")] = ip
|
||||||
if dnsname.HasSuffix(nm.Name, suffix) {
|
if dnsname.HasSuffix(nm.Name, suffix) {
|
||||||
ret[dnsname.TrimSuffix(nm.Name, suffix)] = ip
|
ret[dnsname.TrimSuffix(nm.Name, suffix)] = ip
|
||||||
}
|
}
|
||||||
|
for _, a := range nm.Addresses {
|
||||||
|
if a.IP().Is4() {
|
||||||
|
have4 = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, p := range nm.Peers {
|
for _, p := range nm.Peers {
|
||||||
if p.Name != "" && len(p.Addresses) > 0 {
|
if p.Name == "" {
|
||||||
ip := p.Addresses[0].IP()
|
continue
|
||||||
|
}
|
||||||
|
for _, a := range p.Addresses {
|
||||||
|
ip := a.IP()
|
||||||
|
if ip.Is4() && !have4 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
ret[strings.TrimRight(p.Name, ".")] = ip
|
ret[strings.TrimRight(p.Name, ".")] = ip
|
||||||
if dnsname.HasSuffix(p.Name, suffix) {
|
if dnsname.HasSuffix(p.Name, suffix) {
|
||||||
ret[dnsname.TrimSuffix(p.Name, suffix)] = ip
|
ret[dnsname.TrimSuffix(p.Name, suffix)] = ip
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package netstack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"inet.af/netaddr"
|
||||||
|
"tailscale.com/tailcfg"
|
||||||
|
"tailscale.com/types/netmap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDNSMapFromNetworkMap(t *testing.T) {
|
||||||
|
pfx := netaddr.MustParseIPPrefix
|
||||||
|
ip := netaddr.MustParseIP
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
nm *netmap.NetworkMap
|
||||||
|
want DNSMap
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "self",
|
||||||
|
nm: &netmap.NetworkMap{
|
||||||
|
Name: "foo.tailnet",
|
||||||
|
Addresses: []netaddr.IPPrefix{
|
||||||
|
pfx("100.102.103.104/32"),
|
||||||
|
pfx("100::123/128"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: DNSMap{
|
||||||
|
"foo": ip("100.102.103.104"),
|
||||||
|
"foo.tailnet": ip("100.102.103.104"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "self_and_peers",
|
||||||
|
nm: &netmap.NetworkMap{
|
||||||
|
Name: "foo.tailnet",
|
||||||
|
Addresses: []netaddr.IPPrefix{
|
||||||
|
pfx("100.102.103.104/32"),
|
||||||
|
pfx("100::123/128"),
|
||||||
|
},
|
||||||
|
Peers: []*tailcfg.Node{
|
||||||
|
{
|
||||||
|
Name: "a.tailnet",
|
||||||
|
Addresses: []netaddr.IPPrefix{
|
||||||
|
pfx("100.0.0.201/32"),
|
||||||
|
pfx("100::201/128"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "b.tailnet",
|
||||||
|
Addresses: []netaddr.IPPrefix{
|
||||||
|
pfx("100::202/128"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: DNSMap{
|
||||||
|
"foo": ip("100.102.103.104"),
|
||||||
|
"foo.tailnet": ip("100.102.103.104"),
|
||||||
|
"a": ip("100.0.0.201"),
|
||||||
|
"a.tailnet": ip("100.0.0.201"),
|
||||||
|
"b": ip("100::202"),
|
||||||
|
"b.tailnet": ip("100::202"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "self_has_v6_only",
|
||||||
|
nm: &netmap.NetworkMap{
|
||||||
|
Name: "foo.tailnet",
|
||||||
|
Addresses: []netaddr.IPPrefix{
|
||||||
|
pfx("100::123/128"),
|
||||||
|
},
|
||||||
|
Peers: []*tailcfg.Node{
|
||||||
|
{
|
||||||
|
Name: "a.tailnet",
|
||||||
|
Addresses: []netaddr.IPPrefix{
|
||||||
|
pfx("100.0.0.201/32"),
|
||||||
|
pfx("100::201/128"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "b.tailnet",
|
||||||
|
Addresses: []netaddr.IPPrefix{
|
||||||
|
pfx("100::202/128"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: DNSMap{
|
||||||
|
"foo": ip("100::123"),
|
||||||
|
"foo.tailnet": ip("100::123"),
|
||||||
|
"a": ip("100::201"),
|
||||||
|
"a.tailnet": ip("100::201"),
|
||||||
|
"b": ip("100::202"),
|
||||||
|
"b.tailnet": ip("100::202"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := DNSMapFromNetworkMap(tt.nm)
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("mismatch:\n got %v\nwant %v\n", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue