wgengine, proxymap: split out port mapping from Engine to new type

(Continuing quest to remove rando stuff from the "Engine")

Updates #cleanup

Change-Id: I77f39902c2194410c10c054b545d70c9744250b0
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2023-09-13 11:38:05 -07:00
committed by Brad Fitzpatrick
parent db2f37d7c6
commit 3d37328af6
12 changed files with 106 additions and 82 deletions

View File

@@ -43,6 +43,7 @@ import (
"tailscale.com/net/tsaddr"
"tailscale.com/net/tsdial"
"tailscale.com/net/tstun"
"tailscale.com/proxymap"
"tailscale.com/syncs"
"tailscale.com/tailcfg"
"tailscale.com/types/ipproto"
@@ -121,6 +122,7 @@ type Impl struct {
linkEP *channel.Endpoint
tundev *tstun.Wrapper
e wgengine.Engine
pm *proxymap.Mapper
mc *magicsock.Conn
logf logger.Logf
dialer *tsdial.Dialer
@@ -154,7 +156,7 @@ const nicID = 1
const maxUDPPacketSize = 1500
// Create creates and populates a new Impl.
func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magicsock.Conn, dialer *tsdial.Dialer, dns *dns.Manager) (*Impl, error) {
func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magicsock.Conn, dialer *tsdial.Dialer, dns *dns.Manager, pm *proxymap.Mapper) (*Impl, error) {
if mc == nil {
return nil, errors.New("nil magicsock.Conn")
}
@@ -167,6 +169,9 @@ func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magi
if e == nil {
return nil, errors.New("nil Engine")
}
if pm == nil {
return nil, errors.New("nil proxymap.Mapper")
}
if dialer == nil {
return nil, errors.New("nil Dialer")
}
@@ -209,6 +214,7 @@ func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magi
linkEP: linkEP,
tundev: tundev,
e: e,
pm: pm,
mc: mc,
dialer: dialer,
connsOpenBySubnetIP: make(map[netip.Addr]int),
@@ -984,8 +990,8 @@ func (ns *Impl) forwardTCP(getClient func(...tcpip.SettableSocketOption) *gonet.
backendLocalAddr := server.LocalAddr().(*net.TCPAddr)
backendLocalIPPort := netaddr.Unmap(backendLocalAddr.AddrPort())
ns.e.RegisterIPPortIdentity(backendLocalIPPort, clientRemoteIP)
defer ns.e.UnregisterIPPortIdentity(backendLocalIPPort)
ns.pm.RegisterIPPortIdentity(backendLocalIPPort, clientRemoteIP)
defer ns.pm.UnregisterIPPortIdentity(backendLocalIPPort)
connClosed := make(chan error, 2)
go func() {
_, err := io.Copy(server, client)
@@ -1135,7 +1141,7 @@ func (ns *Impl) forwardUDP(client *gonet.UDPConn, clientAddr, dstAddr netip.Addr
ns.logf("could not get backend local IP:port from %v:%v", backendLocalAddr.IP, backendLocalAddr.Port)
}
if isLocal {
ns.e.RegisterIPPortIdentity(backendLocalIPPort, dstAddr.Addr())
ns.pm.RegisterIPPortIdentity(backendLocalIPPort, dstAddr.Addr())
}
ctx, cancel := context.WithCancel(context.Background())
@@ -1151,7 +1157,7 @@ func (ns *Impl) forwardUDP(client *gonet.UDPConn, clientAddr, dstAddr netip.Addr
}
timer := time.AfterFunc(idleTimeout, func() {
if isLocal {
ns.e.UnregisterIPPortIdentity(backendLocalIPPort)
ns.pm.UnregisterIPPortIdentity(backendLocalIPPort)
}
ns.logf("netstack: UDP session between %s and %s timed out", backendListenAddr, backendRemoteAddr)
cancel()

View File

@@ -53,7 +53,7 @@ func TestInjectInboundLeak(t *testing.T) {
t.Fatal(err)
}
ns, err := Create(logf, tunWrap, eng, sys.MagicSock.Get(), dialer, sys.DNSManager.Get())
ns, err := Create(logf, tunWrap, eng, sys.MagicSock.Get(), dialer, sys.DNSManager.Get(), sys.ProxyMapper())
if err != nil {
t.Fatal(err)
}
@@ -102,7 +102,7 @@ func makeNetstack(t *testing.T, config func(*Impl)) *Impl {
t.Cleanup(func() { eng.Close() })
sys.Set(eng)
ns, err := Create(logf, sys.Tun.Get(), eng, sys.MagicSock.Get(), dialer, sys.DNSManager.Get())
ns, err := Create(logf, sys.Tun.Get(), eng, sys.MagicSock.Get(), dialer, sys.DNSManager.Get(), sys.ProxyMapper())
if err != nil {
t.Fatal(err)
}

View File

@@ -133,7 +133,6 @@ type userspaceEngine struct {
peerSequence []key.NodePublic
endpoints []tailcfg.Endpoint
pendOpen map[flowtrack.Tuple]*pendingOpenFlow // see pendopen.go
tsIPByIPPort map[netip.AddrPort]netip.Addr // allows registration of IP:ports as belonging to a certain Tailscale IP for whois lookups
// pongCallback is the map of response handlers waiting for disco or TSMP
// pong callbacks. The map key is a random slice of bytes.
@@ -1341,50 +1340,6 @@ func (e *userspaceEngine) setICMPEchoResponseCallback(idSeq uint32, cb func()) {
}
}
func (e *userspaceEngine) RegisterIPPortIdentity(ipport netip.AddrPort, tsIP netip.Addr) {
e.mu.Lock()
defer e.mu.Unlock()
if e.tsIPByIPPort == nil {
e.tsIPByIPPort = make(map[netip.AddrPort]netip.Addr)
}
e.tsIPByIPPort[ipport] = tsIP
}
func (e *userspaceEngine) UnregisterIPPortIdentity(ipport netip.AddrPort) {
e.mu.Lock()
defer e.mu.Unlock()
if e.tsIPByIPPort == nil {
return
}
delete(e.tsIPByIPPort, ipport)
}
var whoIsSleeps = [...]time.Duration{
0,
10 * time.Millisecond,
20 * time.Millisecond,
50 * time.Millisecond,
100 * time.Millisecond,
}
func (e *userspaceEngine) WhoIsIPPort(ipport netip.AddrPort) (tsIP netip.Addr, ok bool) {
// We currently have a registration race,
// https://github.com/tailscale/tailscale/issues/1616,
// so loop a few times for now waiting for the registration
// to appear.
// TODO(bradfitz,namansood): remove this once #1616 is fixed.
for _, d := range whoIsSleeps {
time.Sleep(d)
e.mu.Lock()
tsIP, ok = e.tsIPByIPPort[ipport]
e.mu.Unlock()
if ok {
return tsIP, true
}
}
return tsIP, false
}
// PeerForIP returns the Node in the wireguard config
// that's responsible for handling the given IP address.
//

View File

@@ -142,16 +142,6 @@ func (e *watchdogEngine) SetNetworkMap(nm *netmap.NetworkMap) {
func (e *watchdogEngine) Ping(ip netip.Addr, pingType tailcfg.PingType, size int, cb func(*ipnstate.PingResult)) {
e.watchdog("Ping", func() { e.wrap.Ping(ip, pingType, size, cb) })
}
func (e *watchdogEngine) RegisterIPPortIdentity(ipp netip.AddrPort, tsIP netip.Addr) {
e.watchdog("RegisterIPPortIdentity", func() { e.wrap.RegisterIPPortIdentity(ipp, tsIP) })
}
func (e *watchdogEngine) UnregisterIPPortIdentity(ipp netip.AddrPort) {
e.watchdog("UnregisterIPPortIdentity", func() { e.wrap.UnregisterIPPortIdentity(ipp) })
}
func (e *watchdogEngine) WhoIsIPPort(ipp netip.AddrPort) (tsIP netip.Addr, ok bool) {
e.watchdog("UnregisterIPPortIdentity", func() { tsIP, ok = e.wrap.WhoIsIPPort(ipp) })
return tsIP, ok
}
func (e *watchdogEngine) Close() {
e.watchdog("Close", e.wrap.Close)
}

View File

@@ -111,21 +111,6 @@ type Engine interface {
// If size is zero too small, it is ignored. See tailscale.PingOpts for details.
Ping(ip netip.Addr, pingType tailcfg.PingType, size int, cb func(*ipnstate.PingResult))
// RegisterIPPortIdentity registers a given node (identified by its
// Tailscale IP) as temporarily having the given IP:port for whois lookups.
// The IP:port is generally a localhost IP and an ephemeral port, used
// while proxying connections to localhost when tailscaled is running
// in netstack mode.
RegisterIPPortIdentity(netip.AddrPort, netip.Addr)
// UnregisterIPPortIdentity removes a temporary IP:port registration
// made previously by RegisterIPPortIdentity.
UnregisterIPPortIdentity(netip.AddrPort)
// WhoIsIPPort looks up an IP:port in the temporary registrations,
// and returns a matching Tailscale IP, if it exists.
WhoIsIPPort(netip.AddrPort) (netip.Addr, bool)
// InstallCaptureHook registers a function to be called to capture
// packets traversing the data path. The hook can be uninstalled by
// calling this function with a nil value.