| Internet-Draft | UDP Rendezvous | August 2026 |
| Seemann | Expires 17 February 2027 | [Page] |
This document defines an Extended CONNECT protocol for relaying UDP between two clients authenticated by the same proxy. A Listener registers with the proxy, and a Client uses the resulting Rendezvous ID to connect to it. No public UDP address is allocated.¶
This note is to be removed before publishing as an RFC.¶
The latest revision of this draft can be found at https://marten-seemann.github.io/draft-seemann-masque-connect-udp-rendezvous/draft-seemann-masque-connect-udp-rendezvous.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-seemann-masque-connect-udp-rendezvous/.¶
Discussion of this document takes place on the Multiplexed Application Substrate over QUIC Encryption Working Group mailing list (mailto:masque@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/masque/. Subscribe at https://www.ietf.org/mailman/listinfo/masque/.¶
Source for this draft and an issue tracker can be found at https://github.com/marten-seemann/draft-seemann-masque-connect-udp-rendezvous.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 17 February 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
CONNECT-UDP ([RFC9298]) allows an HTTP client to proxy UDP payloads to a fixed remote host and port.¶
This document defines a sibling protocol to CONNECT-UDP for deployments where both endpoints can connect to the same proxy. A Listener opens a long-lived rendezvous request and receives a Rendezvous ID. A Client opens a separate rendezvous request carrying that ID. The proxy associates both requests and forwards HTTP Datagrams ([RFC9297]) between them.¶
One Listener request can serve multiple Clients.¶
Authentication and distribution of Rendezvous IDs are out of scope.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
This document uses the following terms:¶
The endpoint that creates a listener request. A Listener can communicate with multiple Clients on one request.¶
The endpoint that creates a join request. A join request connects to exactly one Listener.¶
An opaque identifier issued by the proxy for a Listener request.¶
The Listener and Client are both HTTP clients.¶
This protocol uses HTTP Extended CONNECT ([RFC8441], [RFC9220]) with the
:protocol pseudo-header field set to connect-udp-rendezvous. It is defined
for HTTP/2 and HTTP/3, but not HTTP/1.1. An endpoint MUST NOT send a rendezvous
request until it has received SETTINGS_ENABLE_CONNECT_PROTOCOL with value 1.¶
Endpoints are configured with an HTTPS URI identifying the rendezvous proxy. A rendezvous request uses this URI as its target.¶
Requests and successful responses use the Capsule Protocol as described in
Section 3.2 of [RFC9297]. The request and successful response MUST contain a
Capsule-Protocol field with value ?1. A successful response has a status code
in the 2xx range. An endpoint MUST abort the request if these requirements are
not met. The proxy MUST NOT interpret the service URI as a UDP target or open a
UDP socket.¶
Connect-UDP-Rendezvous is an Item Structured Header Field ([RFC9651]). Its
bare item is the Token listen or join. The id parameter, when present, is
a Byte Sequence.¶
| Message | Field Value |
|---|---|
| Listener request |
listen
|
| Successful Listener response |
listen; id=:...:
|
| Join request |
join; id=:...:
|
| Successful join response |
join
|
The field MUST NOT appear in trailers. Unknown parameters are ignored. A request with a missing field or a field that cannot be parsed or does not match the table is malformed. The proxy MUST respond with a 400 (Bad Request) status code.¶
A Rendezvous ID is opaque to both endpoints. The proxy MUST NOT issue the same ID for two live Listener requests.¶
An endpoint that receives a successful response without the expected field value MUST abort the request and MUST NOT send HTTP Datagrams on it.¶
The proxy SHOULD use the same error response for an unknown Rendezvous ID and an unauthorized association.¶
HTTP Datagrams use the format defined in Section 5 of [RFC9298] and the Context ID allocation rules from Section 4 of [RFC9298]. A join request uses Context ID 0. When forwarding the first datagram on that request, the proxy allocates a new non-zero odd Context ID on the Listener request and replaces Context ID 0 with it. It uses that Context ID for all datagrams on the join request; the reverse mapping applies to datagrams from the Listener. The proxy MUST NOT reuse a Context ID on the same Listener request, modify a UDP payload, or forward it to more than one association.¶
When the Listener receives a datagram from the proxy with a previously unseen odd Context ID that has not been closed, it registers that Context ID as a new Client association before processing the datagram. The Listener MUST NOT send an HTTP Datagram using the Context ID before receiving it from the proxy.¶
A Listener request MUST NOT carry Context ID 0. A recipient MUST abort the request stream if it receives one. Other unregistered Context IDs are handled as specified in Section 5 of [RFC9298].¶
The proxy MUST drop a datagram that does not fit on the outgoing connection. UDP payloads MUST NOT exceed 65527 octets. An oversized payload on a join request is handled as specified in Section 5 of [RFC9298]; the proxy MUST close the association if it receives an oversized payload from the Listener.¶
A Client MAY send HTTP Datagrams before receiving the response to its join request. The proxy MUST NOT forward a datagram before sending a successful response. It MAY discard or buffer early datagrams. Buffering MUST be bounded; buffered datagrams MUST be discarded if the request is rejected. A Client MUST discard an HTTP/3 Datagram received before the response.¶
The RENDEZVOUS_CLOSE capsule closes one association. It contains exactly one Context ID encoded as a QUIC variable-length integer:¶
RENDEZVOUS_CLOSE Capsule {
Type (i) = TBD1,
Length (i),
Context ID (i),
}
RENDEZVOUS_CLOSE capsules are only sent on Listener requests and MUST carry a non-zero odd Context ID. Receipt on another request, or with a zero or even Context ID, is an error processing the Capsule Protocol. A proxy MUST treat receipt for a Context ID it never allocated as the same error.¶
A RENDEZVOUS_CLOSE capsule sent by the proxy can arrive before the first datagram for that Context ID. The Listener MUST record the Context ID as closed until the Listener request ends and discard later datagrams carrying it. Once the Listener or proxy sends or receives this capsule, it MUST NOT send HTTP Datagrams using that Context ID.¶
Closing or resetting either direction of a rendezvous request causes the proxy to close the other direction. Closing the Listener request also invalidates the Rendezvous ID and closes every join request. Closing a join request causes the proxy to send RENDEZVOUS_CLOSE if the Listener request remains open and a Context ID was allocated, unless it received that capsule from the Listener. A RENDEZVOUS_CLOSE from the Listener causes the proxy to close the corresponding join request.¶
Proxy authentication does not provide end-to-end peer authentication, confidentiality, or integrity. Applications that require these properties use an end-to-end protocol such as QUIC or DTLS.¶
This document requests registration of the following value in the "HTTP Upgrade Tokens" registry:¶
| Value | Description | Expected Version Tokens | Reference |
|---|---|---|---|
| connect-udp-rendezvous | Rendezvous Proxying of UDP Payloads | None | This document |
This document requests registration of the following field in the "Hypertext Transfer Protocol (HTTP) Field Name Registry":¶
| Field Name | Status | Structured Type | Reference |
|---|---|---|---|
| Connect-UDP-Rendezvous | provisional | Item | This document |
This document requests registration of the following value in the "HTTP Capsule Types" registry:¶
| Value | Capsule Type | Status | Reference |
|---|---|---|---|
| TBD1 | RENDEZVOUS_CLOSE | provisional | This document |
The change controller is the IETF and the contact is the MASQUE Working Group (masque@ietf.org).¶