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:
Brad Fitzpatrick
2021-11-30 20:39:12 -08:00
committed by Brad Fitzpatrick
parent bf1d69f25b
commit c37af58ea4
21 changed files with 163 additions and 70 deletions

View File

@@ -36,6 +36,7 @@ import (
"tailscale.com/net/dns"
"tailscale.com/net/interfaces"
"tailscale.com/net/tsaddr"
"tailscale.com/net/tsdial"
"tailscale.com/paths"
"tailscale.com/portlist"
"tailscale.com/tailcfg"
@@ -88,6 +89,7 @@ type LocalBackend struct {
statsLogf logger.Logf // for printing peers stats on change
e wgengine.Engine
store ipn.StateStore
dialer *tsdial.Dialer // non-nil
backendLogID string
unregisterLinkMon 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,
// 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 {
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)
@@ -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),
e: e,
store: store,
dialer: dialer,
backendLogID: logid,
state: ipn.NoState,
portpoll: portpoll,
gotPortPollRes: make(chan struct{}),
}
dialer.SetPeerDialControlFuncGetter(b.peerDialControlFunc)
// Default filter blocks everything and logs nothing, until Start() is called.
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
}
// Dialer returns the backend's dialer.
func (b *LocalBackend) Dialer() *tsdial.Dialer {
return b.dialer
}
// SetDirectFileRoot sets the directory to download files to directly,
// without buffering them through an intermediate daemon-owned
// tailcfg.UserID-specific directory.
@@ -3035,9 +3053,9 @@ func disabledSysctls(sysctls ...string) (disabled []string, err error) {
// bind to dial out to other peers.
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.
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 {
return peerDialControlFunc(b)
}

View File

@@ -445,7 +445,7 @@ func TestLazyMachineKeyGeneration(t *testing.T) {
t.Fatalf("NewFakeUserspaceEngine: %v", err)
}
t.Cleanup(eng.Close)
lb, err := NewLocalBackend(logf, "logid", store, eng)
lb, err := NewLocalBackend(logf, "logid", store, nil, eng)
if err != nil {
t.Fatalf("NewLocalBackend: %v", err)
}

View File

@@ -54,7 +54,7 @@ func TestLocalLogLines(t *testing.T) {
}
t.Cleanup(e.Close)
lb, err := NewLocalBackend(logf, idA.String(), store, e)
lb, err := NewLocalBackend(logf, idA.String(), store, nil, e)
if err != nil {
t.Fatal(err)
}

View File

@@ -284,7 +284,7 @@ func TestStateMachine(t *testing.T) {
t.Cleanup(e.Close)
cc := newMockControl(t)
b, err := NewLocalBackend(logf, "logid", store, e)
b, err := NewLocalBackend(logf, "logid", store, nil, e)
if err != nil {
t.Fatalf("NewLocalBackend: %v", err)
}
@@ -941,7 +941,7 @@ func TestWGEngineStatusRace(t *testing.T) {
eng, err := wgengine.NewFakeUserspaceEngine(logf, 0)
c.Assert(err, qt.IsNil)
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)
cc := newMockControl(t)