diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index e9631c21d..381cef161 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -110,7 +110,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de 💣 tailscale.com/net/netstat from tailscale.com/ipn/ipnserver tailscale.com/net/packet from tailscale.com/wgengine+ tailscale.com/net/portmapper from tailscale.com/net/netcheck+ - tailscale.com/net/socks5 from tailscale.com/cmd/tailscaled + tailscale.com/net/socks5 from tailscale.com/net/socks5/tssocks + tailscale.com/net/socks5/tssocks from tailscale.com/cmd/tailscaled tailscale.com/net/stun from tailscale.com/net/netcheck+ tailscale.com/net/tlsdial from tailscale.com/control/controlclient+ tailscale.com/net/tsaddr from tailscale.com/ipn/ipnlocal+ @@ -154,7 +155,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/wgengine/filter from tailscale.com/control/controlclient+ tailscale.com/wgengine/magicsock from tailscale.com/wgengine+ tailscale.com/wgengine/monitor from tailscale.com/wgengine+ - tailscale.com/wgengine/netstack from tailscale.com/cmd/tailscaled + tailscale.com/wgengine/netstack from tailscale.com/cmd/tailscaled+ tailscale.com/wgengine/router from tailscale.com/cmd/tailscaled+ tailscale.com/wgengine/wgcfg from tailscale.com/ipn/ipnlocal+ tailscale.com/wgengine/wgcfg/nmcfg from tailscale.com/ipn/ipnlocal diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index 0c5223d14..e708d9821 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -24,22 +24,18 @@ "runtime/debug" "strconv" "strings" - "sync" "syscall" "time" "github.com/go-multierror/multierror" - "inet.af/netaddr" "tailscale.com/ipn/ipnserver" "tailscale.com/logpolicy" "tailscale.com/net/dns" - "tailscale.com/net/socks5" - "tailscale.com/net/tsaddr" + "tailscale.com/net/socks5/tssocks" "tailscale.com/net/tstun" "tailscale.com/paths" "tailscale.com/types/flagtype" "tailscale.com/types/logger" - "tailscale.com/types/netmap" "tailscale.com/util/osshare" "tailscale.com/version" "tailscale.com/version/distro" @@ -248,35 +244,7 @@ func run() error { } if socksListener != nil { - srv := &socks5.Server{ - Logf: logger.WithPrefix(logf, "socks5: "), - } - var ( - mu sync.Mutex // guards the following field - dns netstack.DNSMap - ) - e.AddNetworkMapCallback(func(nm *netmap.NetworkMap) { - mu.Lock() - defer mu.Unlock() - dns = netstack.DNSMapFromNetworkMap(nm) - }) - useNetstackForIP := func(ip netaddr.IP) bool { - // TODO(bradfitz): this isn't exactly right. - // We should also support subnets when the - // prefs are configured as such. - return tsaddr.IsTailscaleIP(ip) - } - srv.Dialer = func(ctx context.Context, network, addr string) (net.Conn, error) { - ipp, err := dns.Resolve(ctx, addr) - if err != nil { - return nil, err - } - if ns != nil && useNetstackForIP(ipp.IP()) { - return ns.DialContextTCP(ctx, addr) - } - var d net.Dialer - return d.DialContext(ctx, network, ipp.String()) - } + srv := tssocks.NewServer(logger.WithPrefix(logf, "socks5: "), e, ns) go func() { log.Fatalf("SOCKS5 server exited: %v", srv.Serve(socksListener)) }() diff --git a/net/socks5/socks5.go b/net/socks5/socks5.go index 4303f1a99..12331f3fd 100644 --- a/net/socks5/socks5.go +++ b/net/socks5/socks5.go @@ -2,8 +2,15 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package socks5 is a SOCKS5 server implementation -// for userspace networking in Tailscale. +// Package socks5 is a SOCKS5 server implementation. +// +// This is used for userspace networking in Tailscale. Specifically, +// this is used for dialing out of the machine to other nodes, without +// the host kernel's involvement, so it doesn't proper routing tables, +// TUN, IPv6, etc. This package is meant to only handle the SOCKS5 protocol +// details and not any integration with Tailscale internals itself. +// +// The glue between this package and Tailscale is in net/socks5/tssocks. package socks5 import ( diff --git a/net/socks5/tssocks/tssocks.go b/net/socks5/tssocks/tssocks.go new file mode 100644 index 000000000..d8edb8f77 --- /dev/null +++ b/net/socks5/tssocks/tssocks.go @@ -0,0 +1,60 @@ +// 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/net/tsaddr" + "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 { + srv := &socks5.Server{ + Logf: logf, + } + var ( + mu sync.Mutex // guards the following field + dns netstack.DNSMap + ) + e.AddNetworkMapCallback(func(nm *netmap.NetworkMap) { + mu.Lock() + defer mu.Unlock() + dns = netstack.DNSMapFromNetworkMap(nm) + }) + useNetstackForIP := func(ip netaddr.IP) bool { + // TODO(bradfitz): this isn't exactly right. + // We should also support subnets when the + // prefs are configured as such. + return tsaddr.IsTailscaleIP(ip) + } + srv.Dialer = func(ctx context.Context, network, addr string) (net.Conn, error) { + ipp, err := dns.Resolve(ctx, addr) + if err != nil { + return nil, err + } + if ns != nil && useNetstackForIP(ipp.IP()) { + return ns.DialContextTCP(ctx, addr) + } + var d net.Dialer + return d.DialContext(ctx, network, ipp.String()) + } + return srv +}