diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index cf3945816..a12ef1a31 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -2991,11 +2991,13 @@ type RebindingUDPConn struct { mu sync.Mutex // held while changing pconn (and pconnAtomic) pconn nettype.PacketConn + port uint16 } func (c *RebindingUDPConn) setConnLocked(p nettype.PacketConn) { c.pconn = p c.pconnAtomic.Store(p) + c.port = uint16(c.localAddrLocked().Port) } // currentConn returns c's current pconn, acquiring c.mu in the process. @@ -3057,6 +3059,12 @@ func (c *RebindingUDPConn) ReadFromNetaddr(b []byte) (n int, ipp netip.AddrPort, } } +func (c *RebindingUDPConn) Port() uint16 { + c.mu.Lock() + defer c.mu.Unlock() + return c.port +} + func (c *RebindingUDPConn) LocalAddr() *net.UDPAddr { c.mu.Lock() defer c.mu.Unlock() @@ -3081,6 +3089,7 @@ func (c *RebindingUDPConn) closeLocked() error { if c.pconn == nil { return errNilPConn } + c.port = 0 return c.pconn.Close() } diff --git a/wgengine/magicsock/magicsock_linux.go b/wgengine/magicsock/magicsock_linux.go index 796682de7..ae2c42c52 100644 --- a/wgengine/magicsock/magicsock_linux.go +++ b/wgengine/magicsock/magicsock_linux.go @@ -195,11 +195,11 @@ func (c *Conn) listenRawDisco(family string) (io.Closer, error) { } pc.SetReadDeadline(time.Time{}) - go c.receiveDisco(pc) + go c.receiveDisco(pc, family == "ip6") return pc, nil } -func (c *Conn) receiveDisco(pc net.PacketConn) { +func (c *Conn) receiveDisco(pc net.PacketConn, isIPV6 bool) { var buf [1500]byte for { n, src, err := pc.ReadFrom(buf[:]) @@ -213,6 +213,30 @@ func (c *Conn) receiveDisco(pc net.PacketConn) { // Too small to be a valid UDP datagram, drop. continue } + + dstPort := binary.BigEndian.Uint16(buf[2:4]) + if dstPort == 0 { + c.logf("[unexpected] disco raw: received packet for port 0") + } + + var acceptPort uint16 + if isIPV6 { + acceptPort = c.pconn6.Port() + } else { + acceptPort = c.pconn4.Port() + } + if acceptPort == 0 { + // This should only typically happen if the receiving address family + // was recently disabled. + c.logf("[v1] disco raw: dropping packet for port %d as acceptPort=0", dstPort) + continue + } + + if dstPort != acceptPort { + c.logf("[v1] disco raw: dropping packet for port %d", dstPort) + continue + } + srcIP, ok := netip.AddrFromSlice(src.(*net.IPAddr).IP) if !ok { c.logf("[unexpected] PacketConn.ReadFrom returned not-an-IP %v in from", src)