mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-19 09:30:58 +00:00
proxymap, various: distinguish between different protocols
Previously, we were registering TCP and UDP connections in the same map, which could result in erroneously removing a mapping if one of the two connections completes while the other one is still active. Add a "proto string" argument to these functions to avoid this. Additionally, take the "proto" argument in LocalAPI, and plumb that through from the CLI and add a new LocalClient method. Updates tailscale/corp#20600 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: I35d5efaefdfbf4721e315b8ca123f0c8af9125fb
This commit is contained in:
@@ -9,8 +9,6 @@ import (
|
||||
"net/netip"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"tailscale.com/util/mak"
|
||||
)
|
||||
|
||||
// Mapper tracks which localhost ip:ports correspond to which remote Tailscale
|
||||
@@ -21,26 +19,39 @@ import (
|
||||
// given localhost:port corresponds to.
|
||||
type Mapper struct {
|
||||
mu sync.Mutex
|
||||
m map[netip.AddrPort]netip.Addr
|
||||
m map[string]map[netip.AddrPort]netip.Addr // proto ("tcp", "udp") => ephemeral => tailscale IP
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (m *Mapper) RegisterIPPortIdentity(ipport netip.AddrPort, tsIP netip.Addr) {
|
||||
//
|
||||
// The proto is the network protocol that is being proxied; it must be "tcp" or
|
||||
// "udp" (not e.g. "tcp4", "udp6", etc.)
|
||||
func (m *Mapper) RegisterIPPortIdentity(proto string, ipport netip.AddrPort, tsIP netip.Addr) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
mak.Set(&m.m, ipport, tsIP)
|
||||
if m.m == nil {
|
||||
m.m = make(map[string]map[netip.AddrPort]netip.Addr)
|
||||
}
|
||||
p, ok := m.m[proto]
|
||||
if !ok {
|
||||
p = make(map[netip.AddrPort]netip.Addr)
|
||||
m.m[proto] = p
|
||||
}
|
||||
p[ipport] = tsIP
|
||||
}
|
||||
|
||||
// UnregisterIPPortIdentity removes a temporary IP:port registration
|
||||
// made previously by RegisterIPPortIdentity.
|
||||
func (m *Mapper) UnregisterIPPortIdentity(ipport netip.AddrPort) {
|
||||
func (m *Mapper) UnregisterIPPortIdentity(proto string, ipport netip.AddrPort) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
delete(m.m, ipport)
|
||||
p := m.m[proto]
|
||||
delete(p, ipport) // safe to delete from a nil map
|
||||
}
|
||||
|
||||
var whoIsSleeps = [...]time.Duration{
|
||||
@@ -53,7 +64,7 @@ var whoIsSleeps = [...]time.Duration{
|
||||
|
||||
// WhoIsIPPort looks up an IP:port in the temporary registrations,
|
||||
// and returns a matching Tailscale IP, if it exists.
|
||||
func (m *Mapper) WhoIsIPPort(ipport netip.AddrPort) (tsIP netip.Addr, ok bool) {
|
||||
func (m *Mapper) WhoIsIPPort(proto string, 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
|
||||
@@ -62,7 +73,10 @@ func (m *Mapper) WhoIsIPPort(ipport netip.AddrPort) (tsIP netip.Addr, ok bool) {
|
||||
for _, d := range whoIsSleeps {
|
||||
time.Sleep(d)
|
||||
m.mu.Lock()
|
||||
tsIP, ok = m.m[ipport]
|
||||
p, ok := m.m[proto]
|
||||
if ok {
|
||||
tsIP, ok = p[ipport]
|
||||
}
|
||||
m.mu.Unlock()
|
||||
if ok {
|
||||
return tsIP, true
|
||||
|
Reference in New Issue
Block a user