mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
wgengine/magicsock: use wireguard-go/conn.PeerAwareEndpoint
If we get an non-disco presumably-wireguard-encrypted UDP packet from an IP:port we don't recognize, rather than drop the packet, give it to WireGuard anyway and let WireGuard try to figure out who it's from and tell us. This uses the new hook added in https://github.com/tailscale/wireguard-go/pull/27 Updates tailscale/corp#20732 Change-Id: I5c61a40143810592f9efac6c12808a87f924ecf2 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
49bf63cdd0
commit
808b4139ee
@ -95,6 +95,10 @@ type Knobs struct {
|
||||
// We began creating this rule on 2024-06-14, and this knob
|
||||
// allows us to disable the new behavior remotely if needed.
|
||||
DisableLocalDNSOverrideViaNRPT atomic.Bool
|
||||
|
||||
// DisableCryptorouting indicates that the node should not use the
|
||||
// magicsock crypto routing feature.
|
||||
DisableCryptorouting atomic.Bool
|
||||
}
|
||||
|
||||
// UpdateFromNodeAttributes updates k (if non-nil) based on the provided self
|
||||
@ -122,6 +126,7 @@ func (k *Knobs) UpdateFromNodeAttributes(capMap tailcfg.NodeCapMap) {
|
||||
userDialUseRoutes = has(tailcfg.NodeAttrUserDialUseRoutes)
|
||||
disableSplitDNSWhenNoCustomResolvers = has(tailcfg.NodeAttrDisableSplitDNSWhenNoCustomResolvers)
|
||||
disableLocalDNSOverrideViaNRPT = has(tailcfg.NodeAttrDisableLocalDNSOverrideViaNRPT)
|
||||
disableCryptorouting = has(tailcfg.NodeAttrDisableMagicSockCryptoRouting)
|
||||
)
|
||||
|
||||
if has(tailcfg.NodeAttrOneCGNATEnable) {
|
||||
@ -147,6 +152,7 @@ func (k *Knobs) UpdateFromNodeAttributes(capMap tailcfg.NodeCapMap) {
|
||||
k.UserDialUseRoutes.Store(userDialUseRoutes)
|
||||
k.DisableSplitDNSWhenNoCustomResolvers.Store(disableSplitDNSWhenNoCustomResolvers)
|
||||
k.DisableLocalDNSOverrideViaNRPT.Store(disableLocalDNSOverrideViaNRPT)
|
||||
k.DisableCryptorouting.Store(disableCryptorouting)
|
||||
}
|
||||
|
||||
// AsDebugJSON returns k as something that can be marshalled with json.Marshal
|
||||
@ -173,5 +179,6 @@ func (k *Knobs) AsDebugJSON() map[string]any {
|
||||
"UserDialUseRoutes": k.UserDialUseRoutes.Load(),
|
||||
"DisableSplitDNSWhenNoCustomResolvers": k.DisableSplitDNSWhenNoCustomResolvers.Load(),
|
||||
"DisableLocalDNSOverrideViaNRPT": k.DisableLocalDNSOverrideViaNRPT.Load(),
|
||||
"DisableCryptorouting": k.DisableCryptorouting.Load(),
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,8 @@
|
||||
// - 99: 2024-06-14: Client understands NodeAttrDisableLocalDNSOverrideViaNRPT
|
||||
// - 100: 2024-06-18: Client supports filtertype.Match.SrcCaps (issue #12542)
|
||||
// - 101: 2024-07-01: Client supports SSH agent forwarding when handling connections with /bin/su
|
||||
const CurrentCapabilityVersion CapabilityVersion = 101
|
||||
// - 102: 2024-07-12: NodeAttrDisableMagicSockCryptoRouting support
|
||||
const CurrentCapabilityVersion CapabilityVersion = 102
|
||||
|
||||
type StableID string
|
||||
|
||||
@ -2322,6 +2323,10 @@ type Oauth2Token struct {
|
||||
// We began creating this rule on 2024-06-14, and this node attribute
|
||||
// allows us to disable the new behavior remotely if needed.
|
||||
NodeAttrDisableLocalDNSOverrideViaNRPT NodeCapability = "disable-local-dns-override-via-nrpt"
|
||||
|
||||
// NodeAttrDisableMagicSockCryptoRouting disables the use of the
|
||||
// magicsock cryptorouting hook. See tailscale/corp#20732.
|
||||
NodeAttrDisableMagicSockCryptoRouting NodeCapability = "disable-magicsock-crypto-routing"
|
||||
)
|
||||
|
||||
// SetDNSRequest is a request to add a DNS record.
|
||||
|
@ -1276,7 +1276,8 @@ func (c *Conn) mkReceiveFunc(ruc *RebindingUDPConn, healthItem *health.ReceiveFu
|
||||
//
|
||||
// ok is whether this read should be reported up to wireguard-go (our
|
||||
// caller).
|
||||
func (c *Conn) receiveIP(b []byte, ipp netip.AddrPort, cache *ippEndpointCache) (ep *endpoint, ok bool) {
|
||||
func (c *Conn) receiveIP(b []byte, ipp netip.AddrPort, cache *ippEndpointCache) (_ conn.Endpoint, ok bool) {
|
||||
var ep *endpoint
|
||||
if stun.Is(b) {
|
||||
c.netChecker.ReceiveSTUNPacket(b, ipp)
|
||||
return nil, false
|
||||
@ -1297,8 +1298,11 @@ func (c *Conn) receiveIP(b []byte, ipp netip.AddrPort, cache *ippEndpointCache)
|
||||
de, ok := c.peerMap.endpointForIPPort(ipp)
|
||||
c.mu.Unlock()
|
||||
if !ok {
|
||||
if c.controlKnobs != nil && c.controlKnobs.DisableCryptorouting.Load() {
|
||||
return nil, false
|
||||
}
|
||||
return &lazyEndpoint{c: c, src: ipp}, true
|
||||
}
|
||||
cache.ipp = ipp
|
||||
cache.de = de
|
||||
cache.gen = de.numStopAndReset()
|
||||
@ -3114,3 +3118,35 @@ func (c *Conn) GetLastNetcheckReport(ctx context.Context) *netcheck.Report {
|
||||
func (c *Conn) SetLastNetcheckReportForTest(ctx context.Context, report *netcheck.Report) {
|
||||
c.lastNetCheckReport.Store(report)
|
||||
}
|
||||
|
||||
// lazyEndpoint is a wireguard conn.Endpoint for when magicsock received a
|
||||
// non-disco (presumably WireGuard) packet from a UDP address from which we
|
||||
// can't map to a Tailscale peer. But Wireguard most likely can, once it
|
||||
// decrypts it. So we implement the conn.PeerAwareEndpoint interface
|
||||
// from https://github.com/tailscale/wireguard-go/pull/27 to allow WireGuard
|
||||
// to tell us who it is later and get the correct conn.Endpoint.
|
||||
type lazyEndpoint struct {
|
||||
c *Conn
|
||||
src netip.AddrPort
|
||||
}
|
||||
|
||||
var _ conn.PeerAwareEndpoint = (*lazyEndpoint)(nil)
|
||||
var _ conn.Endpoint = (*lazyEndpoint)(nil)
|
||||
|
||||
func (le *lazyEndpoint) ClearSrc() {}
|
||||
func (le *lazyEndpoint) SrcIP() netip.Addr { return le.src.Addr() }
|
||||
func (le *lazyEndpoint) DstIP() netip.Addr { return netip.Addr{} }
|
||||
func (le *lazyEndpoint) SrcToString() string { return le.src.String() }
|
||||
func (le *lazyEndpoint) DstToString() string { return "dst" }
|
||||
func (le *lazyEndpoint) DstToBytes() []byte { return nil }
|
||||
func (le *lazyEndpoint) GetPeerEndpoint(peerPublicKey [32]byte) conn.Endpoint {
|
||||
pubKey := key.NodePublicFromRaw32(mem.B(peerPublicKey[:]))
|
||||
le.c.mu.Lock()
|
||||
defer le.c.mu.Unlock()
|
||||
ep, ok := le.c.peerMap.endpointForNodeKey(pubKey)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
le.c.logf("magicsock: lazyEndpoint.GetPeerEndpoint(%v) found: %v", pubKey.ShortString(), ep.nodeAddr)
|
||||
return ep
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user