wgengine/netstack: fix shouldProcessInbound peerapi non-SYN handling

It was eating TCP packets to peerapi ports to subnet routers.  Some of
the TCP flow's packets went onward, some got eaten.  So some TCP flows
to subnet routers, if they used an unfortunate TCP port number, got
broken.

Change-Id: Ifea036119ccfb081f4dfa18b892373416a5239f8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/6155/head
Brad Fitzpatrick 2 years ago committed by Brad Fitzpatrick
parent 6d8320a6e9
commit abfdcd0f70

@ -535,23 +535,30 @@ var viaRange = tsaddr.TailscaleViaRange()
// WireGuard peer) should be handled by netstack. // WireGuard peer) should be handled by netstack.
func (ns *Impl) shouldProcessInbound(p *packet.Parsed, t *tstun.Wrapper) bool { func (ns *Impl) shouldProcessInbound(p *packet.Parsed, t *tstun.Wrapper) bool {
// Handle incoming peerapi connections in netstack. // Handle incoming peerapi connections in netstack.
if ns.lb != nil && p.IPProto == ipproto.TCP { dstIP := p.Dst.Addr()
isLocal := ns.isLocalIP(dstIP)
// Handle TCP connection to the Tailscale IP(s) in some cases:
if ns.lb != nil && p.IPProto == ipproto.TCP && isLocal {
var peerAPIPort uint16 var peerAPIPort uint16
dstIP := p.Dst.Addr()
if p.TCPFlags&packet.TCPSynAck == packet.TCPSyn && ns.isLocalIP(dstIP) { if p.TCPFlags&packet.TCPSynAck == packet.TCPSyn {
if port, ok := ns.lb.GetPeerAPIPort(p.Dst.Addr()); ok { if port, ok := ns.lb.GetPeerAPIPort(dstIP); ok {
peerAPIPort = port peerAPIPort = port
atomic.StoreUint32(ns.peerAPIPortAtomic(dstIP), uint32(port)) atomic.StoreUint32(ns.peerAPIPortAtomic(dstIP), uint32(port))
} }
} else { } else {
peerAPIPort = uint16(atomic.LoadUint32(ns.peerAPIPortAtomic(dstIP))) peerAPIPort = uint16(atomic.LoadUint32(ns.peerAPIPortAtomic(dstIP)))
} }
if p.IPProto == ipproto.TCP && p.Dst.Port() == peerAPIPort { dport := p.Dst.Port()
if dport == peerAPIPort {
return true
}
// Also handle SSH connections, if enabled.
if dport == 22 && ns.lb.ShouldRunSSH() {
return true return true
} }
}
if ns.isInboundTSSH(p) && ns.processSSH() {
return true
} }
if p.IPVersion == 6 && viaRange.Contains(p.Dst.Addr()) { if p.IPVersion == 6 && viaRange.Contains(p.Dst.Addr()) {
return ns.lb != nil && ns.lb.ShouldHandleViaIP(p.Dst.Addr()) return ns.lb != nil && ns.lb.ShouldHandleViaIP(p.Dst.Addr())
@ -561,7 +568,6 @@ func (ns *Impl) shouldProcessInbound(p *packet.Parsed, t *tstun.Wrapper) bool {
// netstack isn't used at all; don't even do an isLocalIP lookup. // netstack isn't used at all; don't even do an isLocalIP lookup.
return false return false
} }
isLocal := ns.isLocalIP(p.Dst.Addr())
if ns.ProcessLocalIPs && isLocal { if ns.ProcessLocalIPs && isLocal {
return true return true
} }
@ -647,12 +653,6 @@ func (ns *Impl) userPing(dstIP netip.Addr, pingResPkt []byte) {
} }
} }
func (ns *Impl) isInboundTSSH(p *packet.Parsed) bool {
return p.IPProto == ipproto.TCP &&
p.Dst.Port() == 22 &&
ns.isLocalIP(p.Dst.Addr())
}
// injectInbound is installed as a packet hook on the 'inbound' (from a // injectInbound is installed as a packet hook on the 'inbound' (from a
// WireGuard peer) path. Returning filter.Accept releases the packet to // WireGuard peer) path. Returning filter.Accept releases the packet to
// continue normally (typically being delivered to the host networking stack), // continue normally (typically being delivered to the host networking stack),

Loading…
Cancel
Save