net/tsdial: move macOS/iOS peerapi sockopt logic from LocalBackend

Change-Id: I812cae027c40c70cdc701427b1a1850cd9bcd60c
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2021-12-01 12:07:20 -08:00 committed by Brad Fitzpatrick
parent 25eab78573
commit ad3d6e31f0
7 changed files with 63 additions and 54 deletions

View File

@ -308,8 +308,6 @@ func run() error {
socksListener, httpProxyListener := mustStartProxyListeners(args.socksAddr, args.httpProxyAddr)
dialer := new(tsdial.Dialer) // mutated below (before used)
dialer.SetLinkMonitor(linkMon)
e, useNetstack, err := createEngine(logf, linkMon, dialer)
if err != nil {
logf("wgengine.New: %v", err)

View File

@ -22,7 +22,6 @@
"strings"
"sync"
"sync/atomic"
"syscall"
"time"
"inet.af/netaddr"
@ -192,7 +191,6 @@ func NewLocalBackend(logf logger.Logf, logid string, store ipn.StateStore, diale
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{}))
@ -3041,19 +3039,6 @@ func disabledSysctls(sysctls ...string) (disabled []string, err error) {
return disabled, nil
}
// peerDialControlFunc is non-nil on platforms that require a way to
// 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
// dial other Tailscale peers from the current environment.
func (b *LocalBackend) peerDialControlFunc() func(network, address string, c syscall.RawConn) error {
if peerDialControlFunc != nil {
return peerDialControlFunc(b)
}
return nil
}
// DERPMap returns the current DERPMap in use, or nil if not connected.
func (b *LocalBackend) DERPMap() *tailcfg.DERPMap {
b.mu.Lock()

View File

@ -9,10 +9,8 @@
package ipnlocal
import (
"errors"
"fmt"
"net"
"syscall"
"inet.af/netaddr"
"tailscale.com/net/interfaces"
@ -21,7 +19,6 @@
func init() {
initListenConfig = initListenConfigNetworkExtension
peerDialControlFunc = peerDialControlFuncNetworkExtension
}
// initListenConfigNetworkExtension configures nc for listening on IP
@ -34,24 +31,3 @@ func initListenConfigNetworkExtension(nc *net.ListenConfig, ip netaddr.IP, st *i
}
return netns.SetListenConfigInterfaceIndex(nc, tunIf.Index)
}
func peerDialControlFuncNetworkExtension(b *LocalBackend) func(network, address string, c syscall.RawConn) error {
b.mu.Lock()
defer b.mu.Unlock()
st := b.prevIfState
pas := b.peerAPIServer
index := -1
if st != nil && pas != nil && pas.tunName != "" {
if tunIf, ok := st.Interface[pas.tunName]; ok {
index = tunIf.Index
}
}
var lc net.ListenConfig
netns.SetListenConfigInterfaceIndex(&lc, index)
return func(network, address string, c syscall.RawConn) error {
if index == -1 {
return errors.New("failed to find TUN interface to bind to")
}
return lc.Control(network, address, c)
}
}

View File

@ -739,12 +739,11 @@ func Run(ctx context.Context, logf logger.Logf, ln net.Listener, store ipn.State
}
dialer := new(tsdial.Dialer)
dialer.SetLinkMonitor(linkMon)
eng.AddNetworkMapCallback(func(nm *netmap.NetworkMap) {
dialer.SetDNSMap(tsdial.DNSMapFromNetworkMap(nm))
})
server, err := New(logf, logid, store, eng, nil, serverModeUser, opts)
server, err := New(logf, logid, store, eng, dialer, serverModeUser, opts)
if err != nil {
return err
}

View File

@ -0,0 +1,43 @@
// 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.
// This file's built on iOS and on two of three macOS build variants:
// the two GUI variants that both use Extensions (Network Extension
// and System Extension). It's not used on tailscaled-on-macOS.
//go:build ts_macext && (darwin || ios)
// +build ts_macext
// +build darwin ios
package tsdial
import (
"errors"
"net"
"syscall"
"tailscale.com/net/netns"
)
func init() {
peerDialControlFunc = peerDialControlFuncNetworkExtension
}
func peerDialControlFuncNetworkExtension(d *Dialer) func(network, address string, c syscall.RawConn) error {
d.mu.Lock()
defer d.mu.Unlock()
index := -1
if x, ok := d.interfaceIndexLocked(d.tunName); ok {
index = x
}
var lc net.ListenConfig
netns.SetListenConfigInterfaceIndex(&lc, index)
return func(network, address string, c syscall.RawConn) error {
if index == -1 {
return errors.New("failed to find TUN interface to bind to")
}
return lc.Control(network, address, c)
}
}

View File

@ -67,6 +67,22 @@ func (d *Dialer) SetLinkMonitor(mon *monitor.Mon) {
d.linkMon = mon
}
func (d *Dialer) interfaceIndexLocked(ifName string) (index int, ok bool) {
if d.linkMon == nil {
return 0, false
}
st := d.linkMon.InterfaceState()
iface, ok := st.Interface[ifName]
if !ok {
return 0, false
}
return iface.Index, true
}
// peerDialControlFunc is non-nil on platforms that require a way to
// bind to dial out to other peers.
var peerDialControlFunc func(*Dialer) func(network, address string, c syscall.RawConn) error
// 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.
@ -76,19 +92,10 @@ func (d *Dialer) SetLinkMonitor(mon *monitor.Mon) {
// 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 {
if peerDialControlFunc == 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)
return peerDialControlFunc(d)
}
// SetDNSMap sets the current map of DNS names learned from the netmap.

View File

@ -319,6 +319,7 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
tunName, _ := conf.Tun.Name()
conf.Dialer.SetTUNName(tunName)
conf.Dialer.SetLinkMonitor(e.linkMon)
e.dns = dns.NewManager(logf, conf.DNS, e.linkMon, conf.Dialer, fwdDNSLinkSelector{e, tunName})
logf("link state: %+v", e.linkMon.InterfaceState())