mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-11 21:27:31 +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
@@ -1,90 +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 tssocks is the glue between Tailscale and the net/socks5 package.
|
||||
package tssocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"inet.af/netaddr"
|
||||
"tailscale.com/net/socks5"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/types/netmap"
|
||||
"tailscale.com/wgengine"
|
||||
"tailscale.com/wgengine/netstack"
|
||||
)
|
||||
|
||||
// NewServer returns a new SOCKS5 server configured to dial out to
|
||||
// Tailscale addresses.
|
||||
//
|
||||
// The returned server is not yet listening. The caller must call
|
||||
// Serve with a listener.
|
||||
//
|
||||
// If ns is non-nil, it is used for dialing when needed.
|
||||
func NewServer(logf logger.Logf, e wgengine.Engine, ns *netstack.Impl) *socks5.Server {
|
||||
d := &dialer{ns: ns, eng: e}
|
||||
e.AddNetworkMapCallback(d.onNewNetmap)
|
||||
return &socks5.Server{
|
||||
Logf: logf,
|
||||
Dialer: d.DialContext,
|
||||
}
|
||||
}
|
||||
|
||||
// dialer is the Tailscale SOCKS5 dialer.
|
||||
type dialer struct {
|
||||
ns *netstack.Impl
|
||||
eng wgengine.Engine
|
||||
|
||||
mu sync.Mutex
|
||||
dns netstack.DNSMap
|
||||
}
|
||||
|
||||
func (d *dialer) onNewNetmap(nm *netmap.NetworkMap) {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
d.dns = netstack.DNSMapFromNetworkMap(nm)
|
||||
}
|
||||
|
||||
func (d *dialer) resolve(ctx context.Context, addr string) (netaddr.IPPort, error) {
|
||||
d.mu.Lock()
|
||||
dns := d.dns
|
||||
d.mu.Unlock()
|
||||
return dns.Resolve(ctx, addr)
|
||||
}
|
||||
|
||||
func (d *dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
ipp, err := d.resolve(ctx, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.ns != nil && d.useNetstackForIP(ipp.IP()) {
|
||||
return d.ns.DialContextTCP(ctx, ipp.String())
|
||||
}
|
||||
var stdDialer net.Dialer
|
||||
return stdDialer.DialContext(ctx, network, ipp.String())
|
||||
}
|
||||
|
||||
func (d *dialer) useNetstackForIP(ip netaddr.IP) bool {
|
||||
if d.ns == nil || !d.ns.ProcessLocalIPs {
|
||||
// If netstack isn't used at all (nil), then obviously don't use it.
|
||||
//
|
||||
// But the ProcessLocalIPs check is more subtle: it really means
|
||||
// whether we should use netstack for incoming traffic to ourselves.
|
||||
// It's only ever true if we're running in full netstack mode (no TUN),
|
||||
// so we can also use it as a proxy here for whether TUN is available.
|
||||
// If it's false, there's tun and OS routes to things we need,
|
||||
// so we don't want to dial with netstack.
|
||||
return false
|
||||
}
|
||||
// Otherwise, we're in netstack mode, so dial via netstack if there's
|
||||
// any peer handling that IP (including exit nodes).
|
||||
//
|
||||
// Otherwise assume it's something else (e.g. dialing
|
||||
// google.com:443 via SOCKS) that the caller can dial directly.
|
||||
_, ok := d.eng.PeerForIP(ip)
|
||||
return ok
|
||||
}
|
Reference in New Issue
Block a user