mirror of
https://github.com/go-gost/x.git
synced 2026-10-19 16:16:32 +00:00
The MASQUE handler's CONNECT-UDP path was broken in two ways, so no
standards-compliant client (e.g. Surge) could establish UDP tunnels:
1. Missing Capsule-Protocol response header. HTTPStream() flushes the
response internally and commits the headers, but it was called before
Header().Set("Capsule-Protocol", "?1"), so the mandatory RFC 9298
header was silently dropped and clients rejected the tunnel.
2. WriteTo on a pre-connected socket. A direct UDP dial via the router
returns a *net.UDPConn that satisfies net.PacketConn but is
pre-connected; the relay called WriteTo on it, which fails with "use
of WriteTo with pre-connected connection", so no packet reached the
target.
Set the Capsule-Protocol header before hijacking the stream (dialing the
target first, matching handleConnectTCP), and always wrap the
router-returned conn so writes go through Conn.Write. Verified with a
standards-compliant HTTP/3 MASQUE client: CONNECT-UDP now returns
Capsule-Protocol: ?1 and datagrams relay end to end; CONNECT-TCP
unaffected.