9 Commits
Author SHA1 Message Date
ginuerzh 988c9afe28 fix(masque): reap idle CONNECT-UDP associations
udp.Relay.Run ignored ctx cancellation, so an idle MASQUE association (or a
disconnecting client) leaked its target UDP socket and both copy goroutines,
and service shutdown blocked on the stuck handlers. quic-go's
ReceiveDatagram only unblocks on ctx cancellation, never on stream close, so
closing the datagram conn could not release the read either.

Make Relay.Run cancellation-aware and close both conns on exit, add
WithReadTimeout for an idle read deadline, give DatagramConn a cancelable
context that Close cancels, and apply the parsed idleTimeout to the UDP
relay.

Ref: https://github.com/go-gost/x/issues/128
2026-09-11 21:40:12 +08:00
Vincent Yang a9be7e6dce fix(masque): repair server CONNECT-UDP relay (#122)
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.
2026-08-17 23:05:00 +08:00
ginuerzh 1d34d4543a fix(masque): default enableDatagrams to true on HTTP/3 listener and fix CONNECT-UDP error handling
- listener/http3: default enableDatagrams to true when not explicitly set,
  so CONNECT-UDP (RFC 9298) works out of the box without requiring
  ?enableDatagrams=true in the config URL
- handler/masque: dial target before sending 200 OK in handleConnectUDP,
  matching the handleConnectTCP order; if target dial fails, the handler
  can still return an error status instead of having already committed 200
- handler/masque: add missing WriteHeader(BadRequest) when ResolveUDPAddr
  fails, so the client gets a proper HTTP error instead of an opaque
  H3_REQUEST_CANCELLED stream reset

Fixes #103
2026-06-20 15:01:14 +08:00
ginuerzh 28e5922fce docs(handler/masque): add comprehensive comments for MASQUE proxy handler
Add detailed documentation to the masque handler package covering:
- Package-level doc explaining MASQUE protocol (RFC 9298 CONNECT-UDP,
  RFC 9114 CONNECT-TCP) and request flow
- Doc comments on all exported and unexported types, methods, and structs
- Inline comments explaining HTTP/3 context extraction and data path
- Field-level comments on metadata struct explaining each config param
- Step-by-step flow and data path diagrams for handleConnectUDP and
  handleConnectTCP
2026-06-07 14:29:18 +08:00
ginuerzh 95874c53f5 fix: add status field to service list/detail APIs, unify observeStats retry pattern, fix router bugs
- api: add fillServiceStatus helper and call it from getServiceList/getService
  so status field appears in service list and detail API responses
- observeStats: unify retry pattern across all 9 handlers (http, http2, masque,
  relay, router, socks4, socks5, tungo, tunnel) — buffer events on failure,
  continue to skip fresh collection, clear on success; fix event-loss bug
  where interim events were dropped during retry cycles
- handler/router: check WriteTo/Write return errors in associate.go and
  entrypoint.go; fix DelConnector and ConnectorPool.Del using RLock instead
  of Lock (write under read lock); remove unused fields t and cancel
2026-06-03 22:12:08 +08:00
ginuerzh a9d3ffa496 fix(handler/masque): add recorder stats, idle timeout, reorder auth/DNS/200
Wire pStats into sub-handlers to capture real byte counts from QUIC
streams instead of the dummy listener conn. Resolve target address and
validate capsule-protocol after authentication instead of before 200
response to prevent dead tunnels and unauthenticated probing. Merge
pending observer events rather than replacing on consecutive failures.
Add idle read timeout to TCP tunnel relay. Add doc comments on exported
symbols and NewHandler.
2026-05-31 21:00:00 +08:00
ginuerzh 01a2bbaa11 fix(masque): address review findings for PR #76
- Return errors from MasqueConn.Read/Write instead of silently
  succeeding (prevents infinite busy-loops and silent data loss
  if these methods are accidentally called).
- Set recorder Network field in protocol dispatch switch rather
  than hardcoding "udp", so early errors don't misreport type.
- Clarify that DatagramConn context-ID handling only supports
  context ID 0 (sufficient for CONNECT-UDP per RFC 9298).
2026-05-21 22:50:29 +08:00
David Manouchehri c5f91232cb Add TCP CONNECT support to MASQUE (RFC 9114)
Extend MASQUE implementation to support TCP tunneling via standard HTTP/3
CONNECT method, in addition to existing UDP support via CONNECT-UDP:

- Add StreamConn type for TCP data transfer over HTTP/3 stream body
- Update handler to dispatch based on :protocol pseudo-header:
  - "connect-udp" for UDP (RFC 9298)
  - Empty/"HTTP/3.0" for TCP (RFC 9114)
- Add handleConnectTCP() using bidirectional stream relay
- Update connector to support both TCP and UDP networks
- Add connectTCP() for standard CONNECT requests

TCP uses :authority for target address and stream body for data.
UDP uses path template and HTTP/3 datagrams for data.
2025-12-28 23:47:51 +00:00
David Manouchehri 1752b29df9 Add MASQUE/CONNECT-UDP support (RFC 9298)
Implement UDP tunneling over HTTP/3 using HTTP Datagrams (RFC 9297):
- Add masque handler for server-side CONNECT-UDP
- Add masque connector and h3-masque dialer for client-side
- Add enableDatagrams option to HTTP/3 listener
- Add shared utilities for datagram connections and path parsing

Resource management and connection caching:
- Add deferred stream cleanup in connector on error paths
- Add IsClosed() and Close() methods to Client for proper session management
- Clean up stale cached clients in dialer before reuse
- Close underlying stream when DatagramConn is closed
- Move RequestStream opening from connector to dialer to enable dead
  connection detection and cache invalidation (follows QUIC dialer pattern)
2025-12-28 22:16:54 +00:00