mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-03 06:45:49 +00:00
net/tsdial: move more weirdo dialing into new tsdial package, plumb
Not done yet, but this move more of the outbound dial special casing from random packages into tsdial, which aspires to be the one unified place for all outbound dialing shenanigans. Then this plumbs it all around, so everybody is ultimately holding on to the same dialer. As of this commit, macOS/iOS using an exit node should be able to reach to the exit node's DoH DNS proxy over peerapi, doing the sockopt to stay within the Network Extension. A number of steps remain, including but limited to: * move a bunch more random dialing stuff * make netstack-mode tailscaled be able to use exit node's DNS proxy, teaching tsdial's resolver to use it when an exit node is in use. Updates #1713 Change-Id: I1e8ee378f125421c2b816f47bc2c6d913ddcd2f5 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
bf1d69f25b
commit
c37af58ea4
@ -194,7 +194,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/net/flowtrack from tailscale.com/net/packet+
|
tailscale.com/net/flowtrack from tailscale.com/net/packet+
|
||||||
💣 tailscale.com/net/interfaces from tailscale.com/cmd/tailscaled+
|
💣 tailscale.com/net/interfaces from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/net/netcheck from tailscale.com/wgengine/magicsock
|
tailscale.com/net/netcheck from tailscale.com/wgengine/magicsock
|
||||||
tailscale.com/net/netknob from tailscale.com/ipn/localapi+
|
tailscale.com/net/netknob from tailscale.com/logpolicy+
|
||||||
tailscale.com/net/netns from tailscale.com/cmd/tailscaled+
|
tailscale.com/net/netns from tailscale.com/cmd/tailscaled+
|
||||||
💣 tailscale.com/net/netstat from tailscale.com/ipn/ipnserver
|
💣 tailscale.com/net/netstat from tailscale.com/ipn/ipnserver
|
||||||
tailscale.com/net/packet from tailscale.com/net/tstun+
|
tailscale.com/net/packet from tailscale.com/net/tstun+
|
||||||
|
@ -43,7 +43,6 @@ import (
|
|||||||
"tailscale.com/safesocket"
|
"tailscale.com/safesocket"
|
||||||
"tailscale.com/types/flagtype"
|
"tailscale.com/types/flagtype"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/types/netmap"
|
|
||||||
"tailscale.com/util/clientmetric"
|
"tailscale.com/util/clientmetric"
|
||||||
"tailscale.com/util/multierr"
|
"tailscale.com/util/multierr"
|
||||||
"tailscale.com/util/osshare"
|
"tailscale.com/util/osshare"
|
||||||
@ -308,7 +307,8 @@ func run() error {
|
|||||||
|
|
||||||
socksListener, httpProxyListener := mustStartProxyListeners(args.socksAddr, args.httpProxyAddr)
|
socksListener, httpProxyListener := mustStartProxyListeners(args.socksAddr, args.httpProxyAddr)
|
||||||
|
|
||||||
e, useNetstack, err := createEngine(logf, linkMon)
|
dialer := new(tsdial.Dialer) // mutated below (before used)
|
||||||
|
e, useNetstack, err := createEngine(logf, linkMon, dialer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logf("wgengine.New: %v", err)
|
logf("wgengine.New: %v", err)
|
||||||
return err
|
return err
|
||||||
@ -327,7 +327,6 @@ func run() error {
|
|||||||
log.Fatalf("failed to start netstack: %v", err)
|
log.Fatalf("failed to start netstack: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dialer := new(tsdial.Dialer)
|
|
||||||
if useNetstack {
|
if useNetstack {
|
||||||
dialer.UseNetstackForIP = func(ip netaddr.IP) bool {
|
dialer.UseNetstackForIP = func(ip netaddr.IP) bool {
|
||||||
_, ok := e.PeerForIP(ip)
|
_, ok := e.PeerForIP(ip)
|
||||||
@ -337,13 +336,10 @@ func run() error {
|
|||||||
return ns.DialContextTCP(ctx, dst.String())
|
return ns.DialContextTCP(ctx, dst.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e.AddNetworkMapCallback(func(nm *netmap.NetworkMap) {
|
|
||||||
dialer.SetDNSMap(tsdial.DNSMapFromNetworkMap(nm))
|
|
||||||
})
|
|
||||||
|
|
||||||
if socksListener != nil || httpProxyListener != nil {
|
if socksListener != nil || httpProxyListener != nil {
|
||||||
if httpProxyListener != nil {
|
if httpProxyListener != nil {
|
||||||
hs := &http.Server{Handler: httpProxyHandler(dialer.DialContext)}
|
hs := &http.Server{Handler: httpProxyHandler(dialer.UserDial)}
|
||||||
go func() {
|
go func() {
|
||||||
log.Fatalf("HTTP proxy exited: %v", hs.Serve(httpProxyListener))
|
log.Fatalf("HTTP proxy exited: %v", hs.Serve(httpProxyListener))
|
||||||
}()
|
}()
|
||||||
@ -351,7 +347,7 @@ func run() error {
|
|||||||
if socksListener != nil {
|
if socksListener != nil {
|
||||||
ss := &socks5.Server{
|
ss := &socks5.Server{
|
||||||
Logf: logger.WithPrefix(logf, "socks5: "),
|
Logf: logger.WithPrefix(logf, "socks5: "),
|
||||||
Dialer: dialer.DialContext,
|
Dialer: dialer.UserDial,
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
log.Fatalf("SOCKS5 server exited: %v", ss.Serve(socksListener))
|
log.Fatalf("SOCKS5 server exited: %v", ss.Serve(socksListener))
|
||||||
@ -387,7 +383,7 @@ func run() error {
|
|||||||
logf("ipnserver.StateStore: %v", err)
|
logf("ipnserver.StateStore: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
srv, err := ipnserver.New(logf, pol.PublicID.String(), store, e, nil, opts)
|
srv, err := ipnserver.New(logf, pol.PublicID.String(), store, e, dialer, nil, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logf("ipnserver.New: %v", err)
|
logf("ipnserver.New: %v", err)
|
||||||
return err
|
return err
|
||||||
@ -412,14 +408,14 @@ func run() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createEngine(logf logger.Logf, linkMon *monitor.Mon) (e wgengine.Engine, useNetstack bool, err error) {
|
func createEngine(logf logger.Logf, linkMon *monitor.Mon, dialer *tsdial.Dialer) (e wgengine.Engine, useNetstack bool, err error) {
|
||||||
if args.tunname == "" {
|
if args.tunname == "" {
|
||||||
return nil, false, errors.New("no --tun value specified")
|
return nil, false, errors.New("no --tun value specified")
|
||||||
}
|
}
|
||||||
var errs []error
|
var errs []error
|
||||||
for _, name := range strings.Split(args.tunname, ",") {
|
for _, name := range strings.Split(args.tunname, ",") {
|
||||||
logf("wgengine.NewUserspaceEngine(tun %q) ...", name)
|
logf("wgengine.NewUserspaceEngine(tun %q) ...", name)
|
||||||
e, useNetstack, err = tryEngine(logf, linkMon, name)
|
e, useNetstack, err = tryEngine(logf, linkMon, dialer, name)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return e, useNetstack, nil
|
return e, useNetstack, nil
|
||||||
}
|
}
|
||||||
@ -451,10 +447,11 @@ func shouldWrapNetstack() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryEngine(logf logger.Logf, linkMon *monitor.Mon, name string) (e wgengine.Engine, useNetstack bool, err error) {
|
func tryEngine(logf logger.Logf, linkMon *monitor.Mon, dialer *tsdial.Dialer, name string) (e wgengine.Engine, useNetstack bool, err error) {
|
||||||
conf := wgengine.Config{
|
conf := wgengine.Config{
|
||||||
ListenPort: args.port,
|
ListenPort: args.port,
|
||||||
LinkMonitor: linkMon,
|
LinkMonitor: linkMon,
|
||||||
|
Dialer: dialer,
|
||||||
}
|
}
|
||||||
|
|
||||||
useNetstack = name == "userspace-networking"
|
useNetstack = name == "userspace-networking"
|
||||||
|
@ -36,6 +36,7 @@ import (
|
|||||||
"tailscale.com/net/dns"
|
"tailscale.com/net/dns"
|
||||||
"tailscale.com/net/interfaces"
|
"tailscale.com/net/interfaces"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/paths"
|
"tailscale.com/paths"
|
||||||
"tailscale.com/portlist"
|
"tailscale.com/portlist"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
@ -88,6 +89,7 @@ type LocalBackend struct {
|
|||||||
statsLogf logger.Logf // for printing peers stats on change
|
statsLogf logger.Logf // for printing peers stats on change
|
||||||
e wgengine.Engine
|
e wgengine.Engine
|
||||||
store ipn.StateStore
|
store ipn.StateStore
|
||||||
|
dialer *tsdial.Dialer // non-nil
|
||||||
backendLogID string
|
backendLogID string
|
||||||
unregisterLinkMon func()
|
unregisterLinkMon func()
|
||||||
unregisterHealthWatch func()
|
unregisterHealthWatch func()
|
||||||
@ -155,10 +157,18 @@ type clientGen func(controlclient.Options) (controlclient.Client, error)
|
|||||||
|
|
||||||
// NewLocalBackend returns a new LocalBackend that is ready to run,
|
// NewLocalBackend returns a new LocalBackend that is ready to run,
|
||||||
// but is not actually running.
|
// but is not actually running.
|
||||||
func NewLocalBackend(logf logger.Logf, logid string, store ipn.StateStore, e wgengine.Engine) (*LocalBackend, error) {
|
//
|
||||||
|
// If dialer is nil, a new one is made.
|
||||||
|
func NewLocalBackend(logf logger.Logf, logid string, store ipn.StateStore, dialer *tsdial.Dialer, e wgengine.Engine) (*LocalBackend, error) {
|
||||||
if e == nil {
|
if e == nil {
|
||||||
panic("ipn.NewLocalBackend: wgengine must not be nil")
|
panic("ipn.NewLocalBackend: engine must not be nil")
|
||||||
}
|
}
|
||||||
|
if dialer == nil {
|
||||||
|
dialer = new(tsdial.Dialer)
|
||||||
|
}
|
||||||
|
e.AddNetworkMapCallback(func(nm *netmap.NetworkMap) {
|
||||||
|
dialer.SetDNSMap(tsdial.DNSMapFromNetworkMap(nm))
|
||||||
|
})
|
||||||
|
|
||||||
osshare.SetFileSharingEnabled(false, logf)
|
osshare.SetFileSharingEnabled(false, logf)
|
||||||
|
|
||||||
@ -176,11 +186,14 @@ func NewLocalBackend(logf logger.Logf, logid string, store ipn.StateStore, e wge
|
|||||||
statsLogf: logger.LogOnChange(logf, 5*time.Minute, time.Now),
|
statsLogf: logger.LogOnChange(logf, 5*time.Minute, time.Now),
|
||||||
e: e,
|
e: e,
|
||||||
store: store,
|
store: store,
|
||||||
|
dialer: dialer,
|
||||||
backendLogID: logid,
|
backendLogID: logid,
|
||||||
state: ipn.NoState,
|
state: ipn.NoState,
|
||||||
portpoll: portpoll,
|
portpoll: portpoll,
|
||||||
gotPortPollRes: make(chan struct{}),
|
gotPortPollRes: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
dialer.SetPeerDialControlFuncGetter(b.peerDialControlFunc)
|
||||||
|
|
||||||
// Default filter blocks everything and logs nothing, until Start() is called.
|
// Default filter blocks everything and logs nothing, until Start() is called.
|
||||||
b.setFilter(filter.NewAllowNone(logf, &netaddr.IPSet{}))
|
b.setFilter(filter.NewAllowNone(logf, &netaddr.IPSet{}))
|
||||||
|
|
||||||
@ -210,6 +223,11 @@ func NewLocalBackend(logf logger.Logf, logid string, store ipn.StateStore, e wge
|
|||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dialer returns the backend's dialer.
|
||||||
|
func (b *LocalBackend) Dialer() *tsdial.Dialer {
|
||||||
|
return b.dialer
|
||||||
|
}
|
||||||
|
|
||||||
// SetDirectFileRoot sets the directory to download files to directly,
|
// SetDirectFileRoot sets the directory to download files to directly,
|
||||||
// without buffering them through an intermediate daemon-owned
|
// without buffering them through an intermediate daemon-owned
|
||||||
// tailcfg.UserID-specific directory.
|
// tailcfg.UserID-specific directory.
|
||||||
@ -3035,9 +3053,9 @@ func disabledSysctls(sysctls ...string) (disabled []string, err error) {
|
|||||||
// bind to dial out to other peers.
|
// bind to dial out to other peers.
|
||||||
var peerDialControlFunc func(*LocalBackend) func(network, address string, c syscall.RawConn) error
|
var peerDialControlFunc func(*LocalBackend) func(network, address string, c syscall.RawConn) error
|
||||||
|
|
||||||
// PeerDialControlFunc returns a net.Dialer.Control func (possibly nil) to use to
|
// peerDialControlFunc returns a net.Dialer.Control func (possibly nil) to use to
|
||||||
// dial other Tailscale peers from the current environment.
|
// dial other Tailscale peers from the current environment.
|
||||||
func (b *LocalBackend) PeerDialControlFunc() func(network, address string, c syscall.RawConn) error {
|
func (b *LocalBackend) peerDialControlFunc() func(network, address string, c syscall.RawConn) error {
|
||||||
if peerDialControlFunc != nil {
|
if peerDialControlFunc != nil {
|
||||||
return peerDialControlFunc(b)
|
return peerDialControlFunc(b)
|
||||||
}
|
}
|
||||||
|
@ -445,7 +445,7 @@ func TestLazyMachineKeyGeneration(t *testing.T) {
|
|||||||
t.Fatalf("NewFakeUserspaceEngine: %v", err)
|
t.Fatalf("NewFakeUserspaceEngine: %v", err)
|
||||||
}
|
}
|
||||||
t.Cleanup(eng.Close)
|
t.Cleanup(eng.Close)
|
||||||
lb, err := NewLocalBackend(logf, "logid", store, eng)
|
lb, err := NewLocalBackend(logf, "logid", store, nil, eng)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewLocalBackend: %v", err)
|
t.Fatalf("NewLocalBackend: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ func TestLocalLogLines(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Cleanup(e.Close)
|
t.Cleanup(e.Close)
|
||||||
|
|
||||||
lb, err := NewLocalBackend(logf, idA.String(), store, e)
|
lb, err := NewLocalBackend(logf, idA.String(), store, nil, e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -284,7 +284,7 @@ func TestStateMachine(t *testing.T) {
|
|||||||
t.Cleanup(e.Close)
|
t.Cleanup(e.Close)
|
||||||
|
|
||||||
cc := newMockControl(t)
|
cc := newMockControl(t)
|
||||||
b, err := NewLocalBackend(logf, "logid", store, e)
|
b, err := NewLocalBackend(logf, "logid", store, nil, e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewLocalBackend: %v", err)
|
t.Fatalf("NewLocalBackend: %v", err)
|
||||||
}
|
}
|
||||||
@ -941,7 +941,7 @@ func TestWGEngineStatusRace(t *testing.T) {
|
|||||||
eng, err := wgengine.NewFakeUserspaceEngine(logf, 0)
|
eng, err := wgengine.NewFakeUserspaceEngine(logf, 0)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
t.Cleanup(eng.Close)
|
t.Cleanup(eng.Close)
|
||||||
b, err := NewLocalBackend(logf, "logid", new(ipn.MemoryStore), eng)
|
b, err := NewLocalBackend(logf, "logid", new(ipn.MemoryStore), nil, eng)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
cc := newMockControl(t)
|
cc := newMockControl(t)
|
||||||
|
@ -38,10 +38,12 @@ import (
|
|||||||
"tailscale.com/log/filelogger"
|
"tailscale.com/log/filelogger"
|
||||||
"tailscale.com/logtail/backoff"
|
"tailscale.com/logtail/backoff"
|
||||||
"tailscale.com/net/netstat"
|
"tailscale.com/net/netstat"
|
||||||
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/paths"
|
"tailscale.com/paths"
|
||||||
"tailscale.com/safesocket"
|
"tailscale.com/safesocket"
|
||||||
"tailscale.com/smallzstd"
|
"tailscale.com/smallzstd"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
|
"tailscale.com/types/netmap"
|
||||||
"tailscale.com/util/groupmember"
|
"tailscale.com/util/groupmember"
|
||||||
"tailscale.com/util/pidowner"
|
"tailscale.com/util/pidowner"
|
||||||
"tailscale.com/util/systemd"
|
"tailscale.com/util/systemd"
|
||||||
@ -735,7 +737,12 @@ func Run(ctx context.Context, logf logger.Logf, ln net.Listener, store ipn.State
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server, err := New(logf, logid, store, eng, serverModeUser, opts)
|
dialer := new(tsdial.Dialer)
|
||||||
|
eng.AddNetworkMapCallback(func(nm *netmap.NetworkMap) {
|
||||||
|
dialer.SetDNSMap(tsdial.DNSMapFromNetworkMap(nm))
|
||||||
|
})
|
||||||
|
|
||||||
|
server, err := New(logf, logid, store, eng, nil, serverModeUser, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -748,8 +755,8 @@ func Run(ctx context.Context, logf logger.Logf, ln net.Listener, store ipn.State
|
|||||||
// New returns a new Server.
|
// New returns a new Server.
|
||||||
//
|
//
|
||||||
// To start it, use the Server.Run method.
|
// To start it, use the Server.Run method.
|
||||||
func New(logf logger.Logf, logid string, store ipn.StateStore, eng wgengine.Engine, serverModeUser *user.User, opts Options) (*Server, error) {
|
func New(logf logger.Logf, logid string, store ipn.StateStore, eng wgengine.Engine, dialer *tsdial.Dialer, serverModeUser *user.User, opts Options) (*Server, error) {
|
||||||
b, err := ipnlocal.NewLocalBackend(logf, logid, store, eng)
|
b, err := ipnlocal.NewLocalBackend(logf, logid, store, dialer, eng)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("NewLocalBackend: %v", err)
|
return nil, fmt.Errorf("NewLocalBackend: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -20,7 +19,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
@ -28,7 +26,6 @@ import (
|
|||||||
"tailscale.com/ipn"
|
"tailscale.com/ipn"
|
||||||
"tailscale.com/ipn/ipnlocal"
|
"tailscale.com/ipn/ipnlocal"
|
||||||
"tailscale.com/ipn/ipnstate"
|
"tailscale.com/ipn/ipnstate"
|
||||||
"tailscale.com/net/netknob"
|
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/util/clientmetric"
|
"tailscale.com/util/clientmetric"
|
||||||
@ -442,7 +439,7 @@ func (h *Handler) serveFilePut(w http.ResponseWriter, r *http.Request) {
|
|||||||
outReq.ContentLength = r.ContentLength
|
outReq.ContentLength = r.ContentLength
|
||||||
|
|
||||||
rp := httputil.NewSingleHostReverseProxy(dstURL)
|
rp := httputil.NewSingleHostReverseProxy(dstURL)
|
||||||
rp.Transport = getDialPeerTransport(h.b)
|
rp.Transport = h.b.Dialer().PeerAPITransport()
|
||||||
rp.ServeHTTP(w, outReq)
|
rp.ServeHTTP(w, outReq)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,26 +473,6 @@ func (h *Handler) serveDERPMap(w http.ResponseWriter, r *http.Request) {
|
|||||||
e.Encode(h.b.DERPMap())
|
e.Encode(h.b.DERPMap())
|
||||||
}
|
}
|
||||||
|
|
||||||
var dialPeerTransportOnce struct {
|
|
||||||
sync.Once
|
|
||||||
v *http.Transport
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDialPeerTransport(b *ipnlocal.LocalBackend) *http.Transport {
|
|
||||||
dialPeerTransportOnce.Do(func() {
|
|
||||||
t := http.DefaultTransport.(*http.Transport).Clone()
|
|
||||||
t.Dial = nil
|
|
||||||
dialer := net.Dialer{
|
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
KeepAlive: netknob.PlatformTCPKeepAlive(),
|
|
||||||
Control: b.PeerDialControlFunc(),
|
|
||||||
}
|
|
||||||
t.DialContext = dialer.DialContext
|
|
||||||
dialPeerTransportOnce.v = t
|
|
||||||
})
|
|
||||||
return dialPeerTransportOnce.v
|
|
||||||
}
|
|
||||||
|
|
||||||
func defBool(a string, def bool) bool {
|
func defBool(a string, def bool) bool {
|
||||||
if a == "" {
|
if a == "" {
|
||||||
return def
|
return def
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"tailscale.com/health"
|
"tailscale.com/health"
|
||||||
"tailscale.com/net/dns/resolver"
|
"tailscale.com/net/dns/resolver"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/types/dnstype"
|
"tailscale.com/types/dnstype"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/util/dnsname"
|
"tailscale.com/util/dnsname"
|
||||||
@ -39,11 +40,14 @@ type Manager struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewManagers created a new manager from the given config.
|
// NewManagers created a new manager from the given config.
|
||||||
func NewManager(logf logger.Logf, oscfg OSConfigurator, linkMon *monitor.Mon, linkSel resolver.ForwardLinkSelector) *Manager {
|
func NewManager(logf logger.Logf, oscfg OSConfigurator, linkMon *monitor.Mon, dialer *tsdial.Dialer, linkSel resolver.ForwardLinkSelector) *Manager {
|
||||||
|
if dialer == nil {
|
||||||
|
panic("nil Dialer")
|
||||||
|
}
|
||||||
logf = logger.WithPrefix(logf, "dns: ")
|
logf = logger.WithPrefix(logf, "dns: ")
|
||||||
m := &Manager{
|
m := &Manager{
|
||||||
logf: logf,
|
logf: logf,
|
||||||
resolver: resolver.New(logf, linkMon, linkSel),
|
resolver: resolver.New(logf, linkMon, linkSel, dialer),
|
||||||
os: oscfg,
|
os: oscfg,
|
||||||
}
|
}
|
||||||
m.logf("using %T", m.os)
|
m.logf("using %T", m.os)
|
||||||
@ -230,7 +234,7 @@ func Cleanup(logf logger.Logf, interfaceName string) {
|
|||||||
logf("creating dns cleanup: %v", err)
|
logf("creating dns cleanup: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dns := NewManager(logf, oscfg, nil, nil)
|
dns := NewManager(logf, oscfg, nil, new(tsdial.Dialer), nil)
|
||||||
if err := dns.Down(); err != nil {
|
if err := dns.Down(); err != nil {
|
||||||
logf("dns down: %v", err)
|
logf("dns down: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
"tailscale.com/net/dns/resolver"
|
"tailscale.com/net/dns/resolver"
|
||||||
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/types/dnstype"
|
"tailscale.com/types/dnstype"
|
||||||
"tailscale.com/util/dnsname"
|
"tailscale.com/util/dnsname"
|
||||||
)
|
)
|
||||||
@ -398,7 +399,7 @@ func TestManager(t *testing.T) {
|
|||||||
SplitDNS: test.split,
|
SplitDNS: test.split,
|
||||||
BaseConfig: test.bs,
|
BaseConfig: test.bs,
|
||||||
}
|
}
|
||||||
m := NewManager(t.Logf, &f, nil, nil)
|
m := NewManager(t.Logf, &f, nil, new(tsdial.Dialer), nil)
|
||||||
m.resolver.TestOnlySetHook(f.SetResolver)
|
m.resolver.TestOnlySetHook(f.SetResolver)
|
||||||
|
|
||||||
if err := m.Set(test.in); err != nil {
|
if err := m.Set(test.in); err != nil {
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
"tailscale.com/hostinfo"
|
"tailscale.com/hostinfo"
|
||||||
"tailscale.com/net/netns"
|
"tailscale.com/net/netns"
|
||||||
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/types/dnstype"
|
"tailscale.com/types/dnstype"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/util/dnsname"
|
"tailscale.com/util/dnsname"
|
||||||
@ -159,7 +160,8 @@ type resolverAndDelay struct {
|
|||||||
type forwarder struct {
|
type forwarder struct {
|
||||||
logf logger.Logf
|
logf logger.Logf
|
||||||
linkMon *monitor.Mon
|
linkMon *monitor.Mon
|
||||||
linkSel ForwardLinkSelector
|
linkSel ForwardLinkSelector // TODO(bradfitz): remove this when tsdial.Dialer absords it
|
||||||
|
dialer *tsdial.Dialer
|
||||||
dohSem chan struct{}
|
dohSem chan struct{}
|
||||||
|
|
||||||
ctx context.Context // good until Close
|
ctx context.Context // good until Close
|
||||||
@ -205,11 +207,12 @@ func maxDoHInFlight(goos string) int {
|
|||||||
return 1000
|
return 1000
|
||||||
}
|
}
|
||||||
|
|
||||||
func newForwarder(logf logger.Logf, responses chan packet, linkMon *monitor.Mon, linkSel ForwardLinkSelector) *forwarder {
|
func newForwarder(logf logger.Logf, responses chan packet, linkMon *monitor.Mon, linkSel ForwardLinkSelector, dialer *tsdial.Dialer) *forwarder {
|
||||||
f := &forwarder{
|
f := &forwarder{
|
||||||
logf: logger.WithPrefix(logf, "forward: "),
|
logf: logger.WithPrefix(logf, "forward: "),
|
||||||
linkMon: linkMon,
|
linkMon: linkMon,
|
||||||
linkSel: linkSel,
|
linkSel: linkSel,
|
||||||
|
dialer: dialer,
|
||||||
responses: responses,
|
responses: responses,
|
||||||
dohSem: make(chan struct{}, maxDoHInFlight(runtime.GOOS)),
|
dohSem: make(chan struct{}, maxDoHInFlight(runtime.GOOS)),
|
||||||
}
|
}
|
||||||
@ -423,10 +426,7 @@ func (f *forwarder) sendDoH(ctx context.Context, urlBase string, c *http.Client,
|
|||||||
// send expects the reply to have the same txid as txidOut.
|
// send expects the reply to have the same txid as txidOut.
|
||||||
func (f *forwarder) send(ctx context.Context, fq *forwardQuery, rr resolverAndDelay) ([]byte, error) {
|
func (f *forwarder) send(ctx context.Context, fq *forwardQuery, rr resolverAndDelay) ([]byte, error) {
|
||||||
if strings.HasPrefix(rr.name.Addr, "http://") {
|
if strings.HasPrefix(rr.name.Addr, "http://") {
|
||||||
// TODO(bradfitz): this only work for TUN mode right now; plumb a universal dialer
|
return f.sendDoH(ctx, rr.name.Addr, f.dialer.PeerAPIHTTPClient(), fq.packet)
|
||||||
// that can handle the dozen special cases for modes/platforms/routes.
|
|
||||||
TODOHTTPClient := http.DefaultClient
|
|
||||||
return f.sendDoH(ctx, rr.name.Addr, TODOHTTPClient, fq.packet)
|
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(rr.name.Addr, "https://") {
|
if strings.HasPrefix(rr.name.Addr, "https://") {
|
||||||
metricDNSFwdErrorType.Add(1)
|
metricDNSFwdErrorType.Add(1)
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
dns "golang.org/x/net/dns/dnsmessage"
|
dns "golang.org/x/net/dns/dnsmessage"
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/types/dnstype"
|
"tailscale.com/types/dnstype"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/util/clientmetric"
|
"tailscale.com/util/clientmetric"
|
||||||
@ -192,6 +193,7 @@ func WriteRoutes(w *bufio.Writer, routes map[dnsname.FQDN][]dnstype.Resolver) {
|
|||||||
type Resolver struct {
|
type Resolver struct {
|
||||||
logf logger.Logf
|
logf logger.Logf
|
||||||
linkMon *monitor.Mon // or nil
|
linkMon *monitor.Mon // or nil
|
||||||
|
dialer *tsdial.Dialer // non-nil
|
||||||
saveConfigForTests func(cfg Config) // used in tests to capture resolver config
|
saveConfigForTests func(cfg Config) // used in tests to capture resolver config
|
||||||
// forwarder forwards requests to upstream nameservers.
|
// forwarder forwards requests to upstream nameservers.
|
||||||
forwarder *forwarder
|
forwarder *forwarder
|
||||||
@ -223,7 +225,10 @@ type ForwardLinkSelector interface {
|
|||||||
|
|
||||||
// New returns a new resolver.
|
// New returns a new resolver.
|
||||||
// linkMon optionally specifies a link monitor to use for socket rebinding.
|
// linkMon optionally specifies a link monitor to use for socket rebinding.
|
||||||
func New(logf logger.Logf, linkMon *monitor.Mon, linkSel ForwardLinkSelector) *Resolver {
|
func New(logf logger.Logf, linkMon *monitor.Mon, linkSel ForwardLinkSelector, dialer *tsdial.Dialer) *Resolver {
|
||||||
|
if dialer == nil {
|
||||||
|
panic("nil Dialer")
|
||||||
|
}
|
||||||
r := &Resolver{
|
r := &Resolver{
|
||||||
logf: logger.WithPrefix(logf, "resolver: "),
|
logf: logger.WithPrefix(logf, "resolver: "),
|
||||||
linkMon: linkMon,
|
linkMon: linkMon,
|
||||||
@ -232,8 +237,9 @@ func New(logf logger.Logf, linkMon *monitor.Mon, linkSel ForwardLinkSelector) *R
|
|||||||
closed: make(chan struct{}),
|
closed: make(chan struct{}),
|
||||||
hostToIP: map[dnsname.FQDN][]netaddr.IP{},
|
hostToIP: map[dnsname.FQDN][]netaddr.IP{},
|
||||||
ipToHost: map[netaddr.IP]dnsname.FQDN{},
|
ipToHost: map[netaddr.IP]dnsname.FQDN{},
|
||||||
|
dialer: dialer,
|
||||||
}
|
}
|
||||||
r.forwarder = newForwarder(r.logf, r.responses, linkMon, linkSel)
|
r.forwarder = newForwarder(r.logf, r.responses, linkMon, linkSel, dialer)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
|
|
||||||
dns "golang.org/x/net/dns/dnsmessage"
|
dns "golang.org/x/net/dns/dnsmessage"
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/tstest"
|
"tailscale.com/tstest"
|
||||||
"tailscale.com/types/dnstype"
|
"tailscale.com/types/dnstype"
|
||||||
"tailscale.com/util/dnsname"
|
"tailscale.com/util/dnsname"
|
||||||
@ -308,7 +309,7 @@ func TestRDNSNameToIPv6(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newResolver(t testing.TB) *Resolver {
|
func newResolver(t testing.TB) *Resolver {
|
||||||
return New(t.Logf, nil /* no link monitor */, nil /* no link selector */)
|
return New(t.Logf, nil /* no link monitor */, nil /* no link selector */, new(tsdial.Dialer))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResolveLocal(t *testing.T) {
|
func TestResolveLocal(t *testing.T) {
|
||||||
@ -1062,7 +1063,7 @@ func TestForwardLinkSelection(t *testing.T) {
|
|||||||
return "special"
|
return "special"
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}))
|
}), new(tsdial.Dialer))
|
||||||
|
|
||||||
// Test non-special IP.
|
// Test non-special IP.
|
||||||
if got, err := fwd.packetListener(netaddr.IP{}); err != nil {
|
if got, err := fwd.packetListener(netaddr.IP{}); err != nil {
|
||||||
|
@ -9,9 +9,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
|
"tailscale.com/net/netknob"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Dialer dials out of tailscaled, while taking care of details while
|
// Dialer dials out of tailscaled, while taking care of details while
|
||||||
@ -27,11 +32,43 @@ type Dialer struct {
|
|||||||
// If nil, it's not used.
|
// If nil, it's not used.
|
||||||
NetstackDialTCP func(context.Context, netaddr.IPPort) (net.Conn, error)
|
NetstackDialTCP func(context.Context, netaddr.IPPort) (net.Conn, error)
|
||||||
|
|
||||||
|
peerDialControlFuncAtomic atomic.Value // of func() func(network, address string, c syscall.RawConn) error
|
||||||
|
|
||||||
|
peerClientOnce sync.Once
|
||||||
|
peerClient *http.Client
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
dns DNSMap
|
dns DNSMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PeerDialControlFunc returns a function
|
||||||
|
// that can assigned to net.Dialer.Control to set sockopts or whatnot
|
||||||
|
// to make a dial escape the current platform's network sandbox.
|
||||||
|
//
|
||||||
|
// On many platforms the returned func will be nil.
|
||||||
|
//
|
||||||
|
// Notably, this is non-nil on iOS and macOS when run as a Network or
|
||||||
|
// System Extension (the GUI variants).
|
||||||
|
func (d *Dialer) PeerDialControlFunc() func(network, address string, c syscall.RawConn) error {
|
||||||
|
gf, _ := d.peerDialControlFuncAtomic.Load().(func() func(network, address string, c syscall.RawConn) error)
|
||||||
|
if gf == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return gf()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPeerDialControlFuncGetter sets a function that returns, for the
|
||||||
|
// current network configuration at the time it's called, a function
|
||||||
|
// that can assigned to net.Dialer.Control to set sockopts or whatnot
|
||||||
|
// to make a dial escape the current platform's network sandbox.
|
||||||
|
func (d *Dialer) SetPeerDialControlFuncGetter(getFunc func() func(network, address string, c syscall.RawConn) error) {
|
||||||
|
d.peerDialControlFuncAtomic.Store(getFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDNSMap sets the current map of DNS names learned from the netmap.
|
||||||
func (d *Dialer) SetDNSMap(m DNSMap) {
|
func (d *Dialer) SetDNSMap(m DNSMap) {
|
||||||
|
// TODO(bradfitz): update this to be aware of DNSConfig
|
||||||
|
// ExtraNames and CertDomains.
|
||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
defer d.mu.Unlock()
|
defer d.mu.Unlock()
|
||||||
d.dns = m
|
d.dns = m
|
||||||
@ -44,7 +81,9 @@ func (d *Dialer) resolve(ctx context.Context, addr string) (netaddr.IPPort, erro
|
|||||||
return dns.Resolve(ctx, addr)
|
return dns.Resolve(ctx, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
|
// UserDial connects to the provided network address as if a user were initiating the dial.
|
||||||
|
// (e.g. from a SOCKS or HTTP outbound proxy)
|
||||||
|
func (d *Dialer) UserDial(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
ipp, err := d.resolve(ctx, addr)
|
ipp, err := d.resolve(ctx, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -59,3 +98,31 @@ func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Con
|
|||||||
var stdDialer net.Dialer
|
var stdDialer net.Dialer
|
||||||
return stdDialer.DialContext(ctx, network, ipp.String())
|
return stdDialer.DialContext(ctx, network, ipp.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PeerAPIHTTPClient returns an HTTP Client to call peers' peerapi
|
||||||
|
// endpoints. //
|
||||||
|
// The returned Client must not be mutated; it's owned by the Dialer
|
||||||
|
// and shared by callers.
|
||||||
|
func (d *Dialer) PeerAPIHTTPClient() *http.Client {
|
||||||
|
d.peerClientOnce.Do(func() {
|
||||||
|
t := http.DefaultTransport.(*http.Transport).Clone()
|
||||||
|
t.Dial = nil
|
||||||
|
dialer := net.Dialer{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
KeepAlive: netknob.PlatformTCPKeepAlive(),
|
||||||
|
Control: d.PeerDialControlFunc(),
|
||||||
|
}
|
||||||
|
t.DialContext = dialer.DialContext
|
||||||
|
d.peerClient = &http.Client{Transport: t}
|
||||||
|
})
|
||||||
|
return d.peerClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerAPITransport returns a Transport to call peers' peerapi
|
||||||
|
// endpoints.
|
||||||
|
//
|
||||||
|
// The returned value must not be mutated; it's owned by the Dialer
|
||||||
|
// and shared by callers.
|
||||||
|
func (d *Dialer) PeerAPITransport() *http.Transport {
|
||||||
|
return d.PeerAPIHTTPClient().Transport.(*http.Transport)
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
package tsnet
|
package tsnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
@ -20,12 +21,14 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"inet.af/netaddr"
|
||||||
"tailscale.com/client/tailscale"
|
"tailscale.com/client/tailscale"
|
||||||
"tailscale.com/control/controlclient"
|
"tailscale.com/control/controlclient"
|
||||||
"tailscale.com/ipn"
|
"tailscale.com/ipn"
|
||||||
"tailscale.com/ipn/ipnlocal"
|
"tailscale.com/ipn/ipnlocal"
|
||||||
"tailscale.com/ipn/localapi"
|
"tailscale.com/ipn/localapi"
|
||||||
"tailscale.com/net/nettest"
|
"tailscale.com/net/nettest"
|
||||||
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/smallzstd"
|
"tailscale.com/smallzstd"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/wgengine"
|
"tailscale.com/wgengine"
|
||||||
@ -114,9 +117,11 @@ func (s *Server) start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialer := new(tsdial.Dialer) // mutated below (before used)
|
||||||
eng, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{
|
eng, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{
|
||||||
ListenPort: 0,
|
ListenPort: 0,
|
||||||
LinkMonitor: linkMon,
|
LinkMonitor: linkMon,
|
||||||
|
Dialer: dialer,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -136,6 +141,13 @@ func (s *Server) start() error {
|
|||||||
if err := ns.Start(); err != nil {
|
if err := ns.Start(); err != nil {
|
||||||
return fmt.Errorf("failed to start netstack: %w", err)
|
return fmt.Errorf("failed to start netstack: %w", err)
|
||||||
}
|
}
|
||||||
|
dialer.UseNetstackForIP = func(ip netaddr.IP) bool {
|
||||||
|
_, ok := eng.PeerForIP(ip)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
dialer.NetstackDialTCP = func(ctx context.Context, dst netaddr.IPPort) (net.Conn, error) {
|
||||||
|
return ns.DialContextTCP(ctx, dst.String())
|
||||||
|
}
|
||||||
|
|
||||||
statePath := filepath.Join(s.dir, "tailscaled.state")
|
statePath := filepath.Join(s.dir, "tailscaled.state")
|
||||||
store, err := ipn.NewFileStore(statePath)
|
store, err := ipn.NewFileStore(statePath)
|
||||||
@ -144,7 +156,7 @@ func (s *Server) start() error {
|
|||||||
}
|
}
|
||||||
logid := "tslib-TODO"
|
logid := "tslib-TODO"
|
||||||
|
|
||||||
lb, err := ipnlocal.NewLocalBackend(logf, logid, store, eng)
|
lb, err := ipnlocal.NewLocalBackend(logf, logid, store, dialer, eng)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("NewLocalBackend: %v", err)
|
return fmt.Errorf("NewLocalBackend: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ import (
|
|||||||
_ "tailscale.com/types/flagtype"
|
_ "tailscale.com/types/flagtype"
|
||||||
_ "tailscale.com/types/key"
|
_ "tailscale.com/types/key"
|
||||||
_ "tailscale.com/types/logger"
|
_ "tailscale.com/types/logger"
|
||||||
_ "tailscale.com/types/netmap"
|
|
||||||
_ "tailscale.com/util/clientmetric"
|
_ "tailscale.com/util/clientmetric"
|
||||||
_ "tailscale.com/util/multierr"
|
_ "tailscale.com/util/multierr"
|
||||||
_ "tailscale.com/util/osshare"
|
_ "tailscale.com/util/osshare"
|
||||||
|
@ -33,7 +33,6 @@ import (
|
|||||||
_ "tailscale.com/types/flagtype"
|
_ "tailscale.com/types/flagtype"
|
||||||
_ "tailscale.com/types/key"
|
_ "tailscale.com/types/key"
|
||||||
_ "tailscale.com/types/logger"
|
_ "tailscale.com/types/logger"
|
||||||
_ "tailscale.com/types/netmap"
|
|
||||||
_ "tailscale.com/util/clientmetric"
|
_ "tailscale.com/util/clientmetric"
|
||||||
_ "tailscale.com/util/multierr"
|
_ "tailscale.com/util/multierr"
|
||||||
_ "tailscale.com/util/osshare"
|
_ "tailscale.com/util/osshare"
|
||||||
|
@ -33,7 +33,6 @@ import (
|
|||||||
_ "tailscale.com/types/flagtype"
|
_ "tailscale.com/types/flagtype"
|
||||||
_ "tailscale.com/types/key"
|
_ "tailscale.com/types/key"
|
||||||
_ "tailscale.com/types/logger"
|
_ "tailscale.com/types/logger"
|
||||||
_ "tailscale.com/types/netmap"
|
|
||||||
_ "tailscale.com/util/clientmetric"
|
_ "tailscale.com/util/clientmetric"
|
||||||
_ "tailscale.com/util/multierr"
|
_ "tailscale.com/util/multierr"
|
||||||
_ "tailscale.com/util/osshare"
|
_ "tailscale.com/util/osshare"
|
||||||
|
@ -33,7 +33,6 @@ import (
|
|||||||
_ "tailscale.com/types/flagtype"
|
_ "tailscale.com/types/flagtype"
|
||||||
_ "tailscale.com/types/key"
|
_ "tailscale.com/types/key"
|
||||||
_ "tailscale.com/types/logger"
|
_ "tailscale.com/types/logger"
|
||||||
_ "tailscale.com/types/netmap"
|
|
||||||
_ "tailscale.com/util/clientmetric"
|
_ "tailscale.com/util/clientmetric"
|
||||||
_ "tailscale.com/util/multierr"
|
_ "tailscale.com/util/multierr"
|
||||||
_ "tailscale.com/util/osshare"
|
_ "tailscale.com/util/osshare"
|
||||||
|
@ -37,7 +37,6 @@ import (
|
|||||||
_ "tailscale.com/types/flagtype"
|
_ "tailscale.com/types/flagtype"
|
||||||
_ "tailscale.com/types/key"
|
_ "tailscale.com/types/key"
|
||||||
_ "tailscale.com/types/logger"
|
_ "tailscale.com/types/logger"
|
||||||
_ "tailscale.com/types/netmap"
|
|
||||||
_ "tailscale.com/util/clientmetric"
|
_ "tailscale.com/util/clientmetric"
|
||||||
_ "tailscale.com/util/multierr"
|
_ "tailscale.com/util/multierr"
|
||||||
_ "tailscale.com/util/osshare"
|
_ "tailscale.com/util/osshare"
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
"tailscale.com/net/interfaces"
|
"tailscale.com/net/interfaces"
|
||||||
"tailscale.com/net/packet"
|
"tailscale.com/net/packet"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/net/tshttpproxy"
|
"tailscale.com/net/tshttpproxy"
|
||||||
"tailscale.com/net/tstun"
|
"tailscale.com/net/tstun"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
@ -191,6 +192,10 @@ type Config struct {
|
|||||||
// If nil, a new link monitor is created.
|
// If nil, a new link monitor is created.
|
||||||
LinkMonitor *monitor.Mon
|
LinkMonitor *monitor.Mon
|
||||||
|
|
||||||
|
// Dialer is the dialer to use for outbound connections.
|
||||||
|
// If nil, a new Dialer is created
|
||||||
|
Dialer *tsdial.Dialer
|
||||||
|
|
||||||
// ListenPort is the port on which the engine will listen.
|
// ListenPort is the port on which the engine will listen.
|
||||||
// If zero, a port is automatically selected.
|
// If zero, a port is automatically selected.
|
||||||
ListenPort uint16
|
ListenPort uint16
|
||||||
@ -268,6 +273,9 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
|
|||||||
}
|
}
|
||||||
conf.DNS = d
|
conf.DNS = d
|
||||||
}
|
}
|
||||||
|
if conf.Dialer == nil {
|
||||||
|
conf.Dialer = new(tsdial.Dialer)
|
||||||
|
}
|
||||||
|
|
||||||
var tsTUNDev *tstun.Wrapper
|
var tsTUNDev *tstun.Wrapper
|
||||||
if conf.IsTAP {
|
if conf.IsTAP {
|
||||||
@ -310,7 +318,7 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tunName, _ := conf.Tun.Name()
|
tunName, _ := conf.Tun.Name()
|
||||||
e.dns = dns.NewManager(logf, conf.DNS, e.linkMon, fwdDNSLinkSelector{e, tunName})
|
e.dns = dns.NewManager(logf, conf.DNS, e.linkMon, conf.Dialer, fwdDNSLinkSelector{e, tunName})
|
||||||
|
|
||||||
logf("link state: %+v", e.linkMon.InterfaceState())
|
logf("link state: %+v", e.linkMon.InterfaceState())
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user