From d5e15816b5986a0faf668edd00f52ab76bb94c93 Mon Sep 17 00:00:00 2001 From: mrambossek Date: Fri, 31 Jul 2026 20:46:47 +0200 Subject: [PATCH] =?UTF-8?q?server:=20fix=20egress-MTU=20probe=20=E2=80=94?= =?UTF-8?q?=20connect=20the=20socket=20before=20reading=20IP=5FMTU?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IP_MTU getsockopt returns ENOTCONN on an unconnected socket; the v0.3.4 probe set IP_MTU_DISCOVER and Sendto but never Connect'd, so every probe errored. UDP-connect (no handshake) pins the route so IP_MTU reflects the path; switched to Write (two return values). Sysctl audit already flagged the four real fmr issues in v0.3.4; this makes the MTU proof report. Co-Authored-By: Claude Opus 5 --- server/internal/selftest/mtu_linux.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/server/internal/selftest/mtu_linux.go b/server/internal/selftest/mtu_linux.go index d6e0dff..c273dd4 100644 --- a/server/internal/selftest/mtu_linux.go +++ b/server/internal/selftest/mtu_linux.go @@ -61,18 +61,27 @@ func probeEgressMTU(target string) MTUResult { _ = syscall.SetsockoptInt(fd, syscall.IPPROTO_IPV6, ipv6MTUDiscover, ipv6PMTUDiscDo) } - // Full-size probe: 1500 total − IP/UDP headers (28 v4, 48 v6). - payload := 1472 + // IP_MTU reflects the CONNECTED path's MTU, so the socket must be connected + // (an unconnected socket returns ENOTCONN). No handshake — UDP connect just + // pins the destination and resolves the route. sa := sockaddr(addr, 33434) + if err := syscall.Connect(fd, sa); err != nil { + res.Err = "connect: " + errStr(err) + return res + } + + // Full-size probe: 1500 total − IP/UDP headers (28 v4, 48 v6). A DF send + // larger than the local MTU fails immediately with EMSGSIZE; a path + // reduction updates IP_MTU after the ICMP frag-needed returns, so we send, + // briefly wait, and read the discovered MTU. + payload := 1472 if !is4 { payload = 1452 } - // A DF send larger than the local MTU fails immediately with EMSGSIZE; a - // path reduction updates IP_MTU after the ICMP frag-needed returns, so we - // send, briefly wait, and read the discovered MTU. - _ = syscall.Sendto(fd, make([]byte, payload), 0, sa) + probe := make([]byte, payload) + _, _ = syscall.Write(fd, probe) time.Sleep(700 * time.Millisecond) - _ = syscall.Sendto(fd, make([]byte, payload), 0, sa) // second send observes any reduction + _, _ = syscall.Write(fd, probe) // second send observes any reduction level, opt := syscall.IPPROTO_IP, ipMTU if !is4 {