mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-12 05:37:32 +00:00
net/tsdial: start of new package to unify all outbound dialing complexity
For now this just deletes the net/socks5/tssocks implementation (and the DNSMap stuff from wgengine/netstack) and moves it into net/tsdial. Then initialize a Dialer early in tailscaled, currently only use for the outbound and SOCKS5 proxies. It will be plumbed more later. Notably, it needs to get down into the DNS forwarder for exit node DNS forwading in netstack mode. But it will also absorb all the peerapi setsockopt and netns Dial and tlsdial complexity too. Updates #1713 Change-Id: Ibc6d56ae21a22655b2fa1002d8fc3f2b2ae8b6df Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:

committed by
Brad Fitzpatrick

parent
3ae6f898cf
commit
d5405c66b7
@@ -33,10 +33,10 @@ import (
|
||||
"inet.af/netstack/waiter"
|
||||
"tailscale.com/net/packet"
|
||||
"tailscale.com/net/tsaddr"
|
||||
"tailscale.com/net/tsdial"
|
||||
"tailscale.com/net/tstun"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/types/netmap"
|
||||
"tailscale.com/util/dnsname"
|
||||
"tailscale.com/wgengine"
|
||||
"tailscale.com/wgengine/filter"
|
||||
"tailscale.com/wgengine/magicsock"
|
||||
@@ -79,7 +79,7 @@ type Impl struct {
|
||||
atomicIsLocalIPFunc atomic.Value // of func(netaddr.IP) bool
|
||||
|
||||
mu sync.Mutex
|
||||
dns DNSMap
|
||||
dns tsdial.DNSMap
|
||||
// connsOpenBySubnetIP keeps track of number of connections open
|
||||
// for each subnet IP temporarily registered on netstack for active
|
||||
// TCP connections, so they can be unregistered when connections are
|
||||
@@ -179,59 +179,10 @@ func (ns *Impl) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DNSMap maps MagicDNS names (both base + FQDN) to their first IP.
|
||||
// It should not be mutated once created.
|
||||
type DNSMap map[string]netaddr.IP
|
||||
|
||||
func DNSMapFromNetworkMap(nm *netmap.NetworkMap) DNSMap {
|
||||
ret := make(DNSMap)
|
||||
suffix := nm.MagicDNSSuffix()
|
||||
have4 := false
|
||||
if nm.Name != "" && len(nm.Addresses) > 0 {
|
||||
ip := nm.Addresses[0].IP()
|
||||
ret[strings.TrimRight(nm.Name, ".")] = ip
|
||||
if dnsname.HasSuffix(nm.Name, suffix) {
|
||||
ret[dnsname.TrimSuffix(nm.Name, suffix)] = ip
|
||||
}
|
||||
for _, a := range nm.Addresses {
|
||||
if a.IP().Is4() {
|
||||
have4 = true
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, p := range nm.Peers {
|
||||
if p.Name == "" {
|
||||
continue
|
||||
}
|
||||
for _, a := range p.Addresses {
|
||||
ip := a.IP()
|
||||
if ip.Is4() && !have4 {
|
||||
continue
|
||||
}
|
||||
ret[strings.TrimRight(p.Name, ".")] = ip
|
||||
if dnsname.HasSuffix(p.Name, suffix) {
|
||||
ret[dnsname.TrimSuffix(p.Name, suffix)] = ip
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, rec := range nm.DNS.ExtraRecords {
|
||||
if rec.Type != "" {
|
||||
continue
|
||||
}
|
||||
ip, err := netaddr.ParseIP(rec.Value)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ret[strings.TrimRight(rec.Name, ".")] = ip
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ns *Impl) updateDNS(nm *netmap.NetworkMap) {
|
||||
ns.mu.Lock()
|
||||
defer ns.mu.Unlock()
|
||||
ns.dns = DNSMapFromNetworkMap(nm)
|
||||
ns.dns = tsdial.DNSMapFromNetworkMap(nm)
|
||||
}
|
||||
|
||||
func (ns *Impl) addSubnetAddress(ip netaddr.IP) {
|
||||
@@ -347,49 +298,6 @@ func (ns *Impl) updateIPs(nm *netmap.NetworkMap) {
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve resolves addr into an IP:port using first the MagicDNS contents
|
||||
// of m, else using the system resolver.
|
||||
func (m DNSMap) Resolve(ctx context.Context, addr string) (netaddr.IPPort, error) {
|
||||
ipp, pippErr := netaddr.ParseIPPort(addr)
|
||||
if pippErr == nil {
|
||||
return ipp, nil
|
||||
}
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
// addr is malformed.
|
||||
return netaddr.IPPort{}, err
|
||||
}
|
||||
if net.ParseIP(host) != nil {
|
||||
// The host part of addr was an IP, so the netaddr.ParseIPPort above should've
|
||||
// passed. Must've been a bad port number. Return the original error.
|
||||
return netaddr.IPPort{}, pippErr
|
||||
}
|
||||
port16, err := strconv.ParseUint(port, 10, 16)
|
||||
if err != nil {
|
||||
return netaddr.IPPort{}, fmt.Errorf("invalid port in address %q", addr)
|
||||
}
|
||||
|
||||
// Host is not an IP, so assume it's a DNS name.
|
||||
|
||||
// Try MagicDNS first, else otherwise a real DNS lookup.
|
||||
ip := m[host]
|
||||
if !ip.IsZero() {
|
||||
return netaddr.IPPortFrom(ip, uint16(port16)), nil
|
||||
}
|
||||
|
||||
// No MagicDNS name so try real DNS.
|
||||
var r net.Resolver
|
||||
ips, err := r.LookupIP(ctx, "ip", host)
|
||||
if err != nil {
|
||||
return netaddr.IPPort{}, err
|
||||
}
|
||||
if len(ips) == 0 {
|
||||
return netaddr.IPPort{}, fmt.Errorf("DNS lookup returned no results for %q", host)
|
||||
}
|
||||
ip, _ = netaddr.FromStdIP(ips[0])
|
||||
return netaddr.IPPortFrom(ip, uint16(port16)), nil
|
||||
}
|
||||
|
||||
func (ns *Impl) DialContextTCP(ctx context.Context, addr string) (*gonet.TCPConn, error) {
|
||||
ns.mu.Lock()
|
||||
dnsMap := ns.dns
|
||||
|
@@ -1,112 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user