there exist proxy configuration interfaces that only allow the user to configure the proxy host and the proxy port.  Client implementations of this specification that are constrained by such <del> limitations MUST use the default template which is defined as: </del>  "https://$PROXY_HOST:$PROXY_PORT/.well-known/masque/ udp/{target_host}/{target_port}/" where $PROXY_HOST and $PROXY_PORT are the configured host and port of the proxy respectively.  Proxy <del> deployments SHOULD use the default template to facilitate interoperability with such clients. </del>  3.

This change reduces the strength of recommendation for the default template. It also discusses how clients can figure out whether a server actually supports this template.
Please file an issue so we can have the discussion there instead of on a PR
For future reference, issue has been filed to discuss this topic.
NAME This PR now adjusts the default template recommendation text, instead of removing it.
that the URI template is not correct. Servers MUST NOT return these response codes if the request is well-formed and the URI matches a supported template. Generally, we shy away from saying "server MUST NOT return x status code " in HTTP because there are situations where that's the best thing to do. For example, a MASQUE server could decide that sending a 404 is the best thing to do to hide the existence of a service from a given client.
That paragraph was added as part of , and thinking about it more it adds more confusion that clarity so I'm going to remove the paragraph in .
As the author of this paragraph, I'm concerned about its removal. The purpose of this text is to enable clients to figure out that the template they are using is not correct. This is especially important given the default template, which will almost always be incorrect. Without a rule like this, error codes are specific to a single URI (i.e. a single destination), and the client never knows if MASQUE might work for a different destination. It therefore has to try MASQUE for every destination (even though it will always fail if the template is wrong), or implement and tune a heuristic to abandon the use of MASQUE after failures with many destinations (which creates compatibility problems with MASQUE servers that serve limited destinations).
I'm assuming that by "the template is not correct" you mean "the client was configured with a different URI template than what the UDP proxy expects", please correct me if that's not the case. Since these error codes don't tell the client what URI template they should have used, the clients will not treat any errors in in a different way, so specifying error codes doesn't change any outcome here. This is very much a binary outcome, either it works or it doesn't. Clients will implement heuristics based on this binary response, not on error codes. As Mark points out, error codes can't be used for this purpose in HTTP.
No, HTTP error codes can distinguish between transient failures (e.g. 429), permanent/cacheable failures (e.g. 404), and even non-error results that some clients might not support (e.g. 307/8). The "Proxy-Status" header provides further detail, and is normatively recommended in this draft precisely because a binary response is insufficient. Some clients might indeed do that, but HTTP also has many minimal or nearly-stateless clients for whom heuristics of this kind would be difficult to implement well. Also, the draft provides no mention of any such heuristics, or guidance on how they ought to work. Mark suggested a SHOULD, which does not seem to be the same as "can't be used for this purpose".
What is the purpose of the MAY and SHOULD in the resulting paragraph? In what way would it improve interoperability?
My goal with this text was to enable clients to determine whether an HTTP CONNECT server also supports MASQUE. I'm not too picky about how that works, but there ought to be some way to do it. The "MAY" documents an approved way to do that, and implicitly threatens servers with incompatibility if they don't hold up their end. Whether we say "SHOULD" or "MUST" on the server side, the "MAY" for the client creates an effective normative requirement on servers. To be clear, my main concern here has been that server implementors will be tempted to represent NXDOMAIN or "No Route To Host" as 404, etc. That's a very logical mapping that would break a lot of client heuristics, but is not prohibited by anything in the draft.
I share that goal. The problem is that this gets tricky because in HTTP a server and an origin aren't the same thing. So my thought is that our best outcome is a two-pronged approach: keep CONNECT-UDP simple, browsers will re-use their "if QUIC breaks often, mark QUIC as broken and use TCP" approach publish something more formalized like draft-schwartz-masque-access-descriptions later to have something that solves the problem for more than just CONNECT-UDP I think the underlying realization here is that browsers will need to interop with servers that do the wrong thing via a simple "mark CONNECT-UDP as broken for this proxy" heuristic, and that once they do that, adding requirements on error codes doesn't gain anything that isn't already covered by Proxy-Status
I think that's reasonably likely to be true for browsers, but not all clients are browsers. Part of the problem is that the TCP fallback heuristic is more complicated than that. The client needs to fall back to TCP, see that TCP works, and only then attribute the failure as likely proxy-related. This is only possible if the proxy client is also the HTTP client, able to change the HTTP version. It does not work for system-level proxy layers, as they cannot control, or even track, UDP->TCP fallback. Ultimately, some heuristic somewhere will probably make it work, but we're creating waste and delay that could be avoided by giving some clear instructions about how to tell if this thing is a MASQUE proxy.
I agree, though I'm not aware of system proxy layers having plans to implement CONNECT-UDP just yet. By the time those happen we'll have a more formalized approach. We can't avoid waste and delay with SHOULDs and MAYs so might as well wait for the formalized solution to tackle that problem.
I suggested a SHOULD because saying that you MUST send a particular status code in a particular situation precludes sending other status codes that might be more relevant. It also encourages clients to equate seeing that status code to only that error condition, even when it might have been generated by another component. However, there's something else going on here -- If you want to say something about many resources, it's best to do so explicitly. While you can infer things about server state from a few HTTP status codes (e.g., 505), most are specific to the resource in question. Saying otherwise is changing the semantics of those status codes, and that isn't something this specification can do.
The default template's purpose is to enable compatibility with origin-only proxy configuration schemes. This is a worthwhile goal, but the default template is not a suitable solution: It violates RFC 8615's definition of .well-known/ as the location for metadata about an origin. A MASQUE service is not metadata. It is not representable as a .well-known "URI suffix" as required by the .well-known registry (unless we register all (2^128 + 2^32)2^16 distinct paths). It conflicts with better discovery mechanisms, like the one in the MASQUE development process. It is not compatible with the use of HTTPS records. (In the targeted legacy context, the client has no other DNS server that can be used when a proxy is in use.) This is somewhat ironic, as HTTPS records allow bootstrapping QUIC connections, and proxying for QUIC is the primary motivation for CONNECT-UDP. We should defer this problem to a subsequent draft, and provide a cohesive proxy setup flow, presumably with a standardized configuration object that could be served from .well-known/ and extended to cover CONNECT-IP, DoH and other relevant capabilities.
Fundamentally I disagree with your assessment that this solution isn't good and should be removed. This serves a real purpose. Let's go into the issues individually: Those points are not an argument to remove the default template, they are an argument to revert PR and switch back to a non-well-known prefix. Let's set those aside for now. I don't see a conflict here: the default template doesn't preclude using other templates that have been discovered through other means. Can you clarify what the conflict is? Can you clarify what the incompatibility is here? I don't understand what the relationship between the default template and HTTPS records is. Clients are welcome to query their own HTTPS records before using CONNECT or CONNECT-UDP. The way that the client picks its template has no impact on its DNS settings.
... This is called "squatting on the HTTP namespace", and it would violate the in RFC 7320. It's also messy to implement, as it would require mixing MASQUE-specific "routing" rules with the user's application-specific routing rules. It doesn't prevent better discovery mechanisms, but it doesn't encourage them either. From the server side, there would be no way to "opt out" of the default path, due to the potential for clients that have implemented this specification but not a later, better discovery mechanism. Servers that would prefer a different path would still have to operate the default path for backwards-compatibility. The relationship is that the default template cannot express the existence of a DNS server affiliated with the MASQUE server. No, they are not, as this would violate the privacy guarantees implicit in the legacy proxy settings UI that this feature is trying to preserve.
You're conflating two types of proxies here: traditional enterprise proxies that speak CONNECT today and can be updated to speak CONNECT-UDP privacy proxies designed to protect a user's privacy from the network Folks won't ever be deploying both of these use cases on the same proxy. Your concerns are valid but they only apply to (2). (2) would never use the default template. The default template only applies to (1).
Client software generally can't tell why a proxy is being used. It just knows that an HTTP CONNECT proxy has been configured with a particular protocol, domain, and port. Its behavior has to be correct for any existing use case. I don't see why privacy proxies wouldn't use the default template. Privacy proxies that are configured via the existing Secure Web Proxy configuration mechanisms (e.g. browser extensions, system settings) would have no other way to use MASQUE. Also, I think this distinction is false. Enterprises are free to use HTTP CONNECT proxies to conceal certain information from the network (e.g. using an employees-only browser extension), and enterprises are often opinionated about which DNS server ought to be used (not controllable via a browser extension).
For completeness, here's how I think this ought to look: URL
Your discovery draft sounds great - however the default template doesn't get in the way of that. I don't think it's reasonable to remove a useful feature because we might have a more complete solution later when the useful feature doesn't get in the way of the future complete solution.
Thanks for the offline discussion, this seems like a good compromise.

there exist proxy configuration interfaces that only allow the user to configure the proxy host and the proxy port.  Client implementations of this specification that are constrained by such  <ins> limitations MAY attempt to access UDP Proxying capabilities using the default template, which is defined as: </ins> "https://$PROXY_HOST:$PROXY_PORT/.well-known/masque/ udp/{target_host}/{target_port}/" where $PROXY_HOST and $PROXY_PORT are the configured host and port of the proxy respectively.  Proxy  <ins> deployments SHOULD offer service at this location if they need to interoperate with such clients. Clients MAY interpret HTTP 400, 404, or 405 response codes as indications that the URI template is not correct.  Servers MUST NOT return these response codes if the request is well-formed and the URI matches a supported template. </ins> 3.


This document describes how to proxy UDP over HTTP.  Similar to how the CONNECT method allows proxying TCP over HTTP, this document <del> defines a new mechanism to proxy UDP.  It is built using HTTP Extended CONNECT. </del>  1.

That omits the HTTP/1.1 support that you have. Is that intentional?
You're right that should be fixed - the intro is correct but the abstract needs to be updated to look more like the corresponding text in the into

This document describes how to proxy UDP over HTTP.  Similar to how the CONNECT method allows proxying TCP over HTTP, this document  <ins> defines a new mechanism to proxy UDP.  When using HTTP/2 or HTTP/3, it uses Extended CONNECT; when using HTTP/1.1, it uses Upgrade. </ins> 1.


capitals, as shown here. In this document, we use the term "proxy" to refer to the HTTP server <del> that opens the UDP socket and responds to the UDP proxying request. If there are HTTP intermediaries (as defined in HTTP) between the client and the proxy, those are referred to as "intermediaries" in this document. </del>  Note that, when the HTTP version in use does not support multiplexing streams (such as HTTP/1.1), any reference to "stream" in this

In the notational conventions Some might argue an HTTP/3 server already opend a UDP socket :-) so you might want to tighten this a bit to say something like In this document, we use the term "proxy" to refer to the HTTP server that acts upon the client request to open a UDP socket to a target server, and generates the response to this request.

capitals, as shown here. In this document, we use the term "proxy" to refer to the HTTP server  <ins> that acts upon the client's UDP proxying request to open a UDP socket to a target server, and generates the response to this request.  If there are HTTP intermediaries (as defined in HTTP) between the client and the proxy, those are referred to as "intermediaries" in this document. </ins> Note that, when the HTTP version in use does not support multiplexing streams (such as HTTP/1.1), any reference to "stream" in this


2. <del> Clients are configured to use UDP Proxying over HTTP via an URI </del>  Template TEMPLATE with the variables "target_host" and "target_port". Examples are shown below: <del> The URI template MUST be a level 3 template or lower.  The URI template MUST be in absolute form, and MUST include non-empty scheme, </del>  authority and path components.  The path component of the URI <del> template MUST start with a slash "/".  All template variables MUST be </del>  within the path component of the URI.  The URI template MUST contain the two variables "target_host" and "target_port" and MAY contain <del> other variables.  The URI template MUST NOT contain any non-ASCII </del>  unicode characters and MUST only contain ASCII characters in the range 0x21-0x7E inclusive (note that percent-encoding is allowed). <del> The URI template MUST NOT use Reserved Expansion ("+" operator), </del>  Fragment Expansion ("#" operator), Label Expansion with Dot-Prefix, Path Segment Expansion with Slash-Prefix, nor Path-Style Parameter Expansion with Semicolon-Prefix.  If any of the requirements above <del> are not met by a URI template, the client MUST reject its </del>  configuration and fail the request without sending it to the proxy. Since the original HTTP CONNECT method allowed conveying the target A "connect-udp" request requests that the recipient proxy establish a tunnel over a single HTTP stream to the destination target identified <del> by the "target_host" and "target_port" variables of the URI template </del>  (see client-config).  If the request is successful, the proxy commits to converting received HTTP Datagrams into UDP packets and vice versa until the tunnel is closed.  Tunnels are commonly used to create an QUIC or another protocol running over UDP. When sending its UDP proxying request, the client SHALL perform URI <del> template expansion to determine the path and query of its request. </del>  target_host supports using DNS names, IPv6 literals and IPv4 <del> literals.  Note that this URI template expansion requires using pct- </del>  encoding, so for example if the target_host is "2001:db8::42", it will be encoded in the URI as "2001%3Adb8%3A%3A42". the request SHALL include a single "Upgrade" header with value "connect-udp". <del> For example, if the client is configured with URI template </del>  "https://proxy.example.org/.well-known/masque/ udp/{target_host}/{target_port}/" and wishes to open a UDP proxying tunnel to target 192.0.2.42:443, it could send the following request: The ":path" and ":scheme" pseudo-header fields SHALL NOT be empty. Their values SHALL contain the scheme and path from the URI <del> template after the URI template expansion process has been </del>  completed. A UDP proxying request that does not conform to these restrictions is malformed (see H2). <del> For example, if the client is configured with URI template </del>  "https://proxy.example.org/{target_host}/{target_port}/" and wishes to open a UDP proxying tunnel to target 192.0.2.42:443, it could send the following request:

-> a URI Template
but also is it "URI Template" or "URI template"? this seems inconsistent through the document

2.  <ins> Clients are configured to use UDP Proxying over HTTP via a URI </ins> Template TEMPLATE with the variables "target_host" and "target_port". Examples are shown below:  <ins> The URI Template MUST be a level 3 template or lower.  The URI Template MUST be in absolute form, and MUST include non-empty scheme, </ins> authority and path components.  The path component of the URI  <ins> Template MUST start with a slash "/".  All template variables MUST be </ins> within the path component of the URI.  The URI template MUST contain the two variables "target_host" and "target_port" and MAY contain  <ins> other variables.  The URI Template MUST NOT contain any non-ASCII </ins> unicode characters and MUST only contain ASCII characters in the range 0x21-0x7E inclusive (note that percent-encoding is allowed).  <ins> The URI Template MUST NOT use Reserved Expansion ("+" operator), </ins> Fragment Expansion ("#" operator), Label Expansion with Dot-Prefix, Path Segment Expansion with Slash-Prefix, nor Path-Style Parameter Expansion with Semicolon-Prefix.  If any of the requirements above  <ins> are not met by a URI Template, the client MUST reject its </ins> configuration and fail the request without sending it to the proxy. Since the original HTTP CONNECT method allowed conveying the target A "connect-udp" request requests that the recipient proxy establish a tunnel over a single HTTP stream to the destination target identified  <ins> by the "target_host" and "target_port" variables of the URI Template </ins> (see client-config).  If the request is successful, the proxy commits to converting received HTTP Datagrams into UDP packets and vice versa until the tunnel is closed.  Tunnels are commonly used to create an QUIC or another protocol running over UDP. When sending its UDP proxying request, the client SHALL perform URI  <ins> Template expansion to determine the path and query of its request. </ins> target_host supports using DNS names, IPv6 literals and IPv4  <ins> literals.  Note that this URI Template expansion requires using pct- </ins> encoding, so for example if the target_host is "2001:db8::42", it will be encoded in the URI as "2001%3Adb8%3A%3A42". the request SHALL include a single "Upgrade" header with value "connect-udp".  <ins> For example, if the client is configured with URI Template </ins> "https://proxy.example.org/.well-known/masque/ udp/{target_host}/{target_port}/" and wishes to open a UDP proxying tunnel to target 192.0.2.42:443, it could send the following request: The ":path" and ":scheme" pseudo-header fields SHALL NOT be empty. Their values SHALL contain the scheme and path from the URI  <ins> Template after the URI template expansion process has been </ins> completed. A UDP proxying request that does not conform to these restrictions is malformed (see H2).  <ins> For example, if the client is configured with URI Template </ins> "https://proxy.example.org/{target_host}/{target_port}/" and wishes to open a UDP proxying tunnel to target 192.0.2.42:443, it could send the following request:


encoding, so for example if the target_host is "2001:db8::42", it will be encoded in the URI as "2001%3Adb8%3A%3A42". <del> A payload within a UDP proxying request message has no defined semantics; a UDP proxying request with a non-empty payload is malformed. </del>  Responses to UDP proxying requests are not cacheable.

"A payload within a UDP proxying request message has no defined semantics; a UDP proxying request with a non-empty payload is malformed." "payload" here I assume is HTTP message content?
Already discussed in and fixed in
... or "message content" There's a lot of uses of UDP payload that do not qualify here. The one example I can see that would benefit from a change is please check if there are any other cases though.

encoding, so for example if the target_host is "2001:db8::42", it will be encoded in the URI as "2001%3Adb8%3A%3A42".  <ins> By virtue of the definition of the Capsule Protocol (see HTTP-DGRAM), UDP proxying requests do not carry any message content.  Similarly, successful UDP proxying responses also do not carry any message content. </ins> Responses to UDP proxying requests are not cacheable.


the origin of the proxy. the request SHALL include a single "Connection" header field with <del> value "Upgrade". </del>  the request SHALL include a single "Upgrade" header field with value "connect-udp". Protocols). the reponse SHALL include a single "Connection" header field with <del> value "Upgrade". </del>  the response SHALL include a single "Upgrade" header field with value "connect-udp".

This is really about case-sensitivity. The Connection header field value is case-insensitive - URL The requirement is uppercase but example uses lowercase. Without citing or mentioning the case sensitivity, readers might be confused, and pedants might complain

the origin of the proxy. the request SHALL include a single "Connection" header field with  <ins> value "Upgrade" (note that this requirement is case-insensitive as per HTTP). </ins> the request SHALL include a single "Upgrade" header field with value "connect-udp". Protocols). the reponse SHALL include a single "Connection" header field with  <ins> value "Upgrade" (note that this requirement is case-insensitive as per HTTP). </ins> the response SHALL include a single "Upgrade" header field with value "connect-udp".


3.4. <del> When using HTTP/2 H2 or HTTP/3 H3, UDP proxying requests use HTTP pseudo-header fields with the following requirements: </del>  The ":method" pseudo-header field SHALL be "CONNECT".

It's mentioned in the abstract and intro but I think it would be useful to remind people that there are prerequisites required to use extended CONNECT in the section that details the specific requirements.

3.4.  <ins> When using HTTP/2 H2 or HTTP/3 H3, UDP proxying requests use Extended CONNECT.  This requires that servers send an HTTP Setting as specified in EXT-CONNECT2 and EXT-CONNECT3, and that requests use HTTP pseudo-header fields with the following requirements: </ins> The ":method" pseudo-header field SHALL be "CONNECT".


IDs are client-allocated, and odd-numbered context IDs are proxy- allocated.  The context ID namespace is tied to a given HTTP request: it is possible for a context ID with the same numeric value to be <del> simultaneously assigned different semantics in distinct requests, potentially with different semantics.  Context IDs MUST NOT be re- allocated within a given HTTP namespace but MAY be allocated in any order.  Once allocated, any context ID can be used by both client and proxy - only allocation carries separate namespaces to avoid requiring synchronization. </del>  Registration is the action by which an endpoint informs its peer of the semantics and format of a given context ID.  This document does

I'm having trouble grokking this, is the mention of "different semantics" duplicate text or is it meant to apply to different things?

IDs are client-allocated, and odd-numbered context IDs are proxy- allocated.  The context ID namespace is tied to a given HTTP request: it is possible for a context ID with the same numeric value to be  <ins> simultaneously allocated in distinct requests, potentially with different semantics.  Context IDs MUST NOT be re-allocated within a given HTTP namespace but MAY be allocated in any order.  Once allocated, any context ID can be used by both client and proxy - only allocation carries separate namespaces to avoid requiring synchronization. </ins> Registration is the action by which an endpoint informs its peer of the semantics and format of a given context ID.  This document does


header fields or capsules to register contexts.  Depending on the method being used, it is possible for datagrams to be received with Context IDs which have not yet been registered, for instance due to <del> reordering of the datagram and the registration packets during transmission. </del>  5.

There's a danger people read too much into "datagram packets" or "registration packets". I think it would be clearer to say something like "due to reordering of packets that contain datagrams or registration messages"

header fields or capsules to register contexts.  Depending on the method being used, it is possible for datagrams to be received with Context IDs which have not yet been registered, for instance due to  <ins> reordering of the packet containing the datagram and the packet containing the registration message during transmission. </ins> 5.


However, in practice denial of service attacks target open TCP ports so the TCP SYN-ACK does not offer much protection in real scenarios.  8. 8.1.

All of these should apply here, doesn't hurt to remind people. Especially the bit in the other spec that says Tokens, it is not accessible from Web Platform APIs (such as those commonly accessed via JavaScript in web browsers).

However, in practice denial of service attacks target open TCP ports so the TCP SYN-ACK does not offer much protection in real scenarios. <ins> The security considerations described in HTTP-DGRAM also apply here. </ins> 8. 8.1.


request with a failure, or if the datagrams are received by the proxy before the request. <del> Endpoints MUST NOT send HTTP Datagrams with payloads longer than 65527 using Context ID zero.  An endpoint that receives a DATAGRAM capsule using Context ID zero whose payload is longer than 65527 MUST </del>  abort the stream.  If a proxy knows it can only send out UDP packets of a certain length due to its underlying link MTU, it SHOULD discard <del> incoming DATAGRAM capsules using Context ID zero whose payload is longer than that limit without buffering the capsule contents. </del>  6.

The last paragraph of section 5, considers payload length There's a small chance for confusion here, because the DATAGRAM capsule format has a field and has a field. Consider therefore explicitly illustrating the maths that is required to determine the payload for which your 65527 limit MUST apply. I.e. this would be calculated by looking at the Capsule's length value and subtracting the encoded length of the Context ID field. (or whatever the answer is, in case I got it wrong)

request with a failure, or if the datagrams are received by the proxy before the request.  <ins> By virtue of the definition of the UDP header UDP, it is not possible to encode UDP payloads longer than 65527 bytes.  Therefore, endpoints MUST NOT send HTTP Datagrams with a Payload field longer than 65527 using Context ID zero.  An endpoint that receives a DATAGRAM capsule using Context ID zero whose Payload field is longer than 65527 MUST </ins> abort the stream.  If a proxy knows it can only send out UDP packets of a certain length due to its underlying link MTU, it SHOULD discard  <ins> incoming DATAGRAM capsules using Context ID zero whose Payload field is longer than that limit without buffering the capsule contents. </ins> 6.


octets" in UDP). Clients MAY optimistically start sending proxied UDP packets before <del> receiving the response to its UDP proxying request, noting however that those may not be processed by the proxy if it responds to the request with a failure, or if the datagrams are received by the proxy before the request. </del>  By virtue of the definition of the UDP header UDP, it is not possible to encode UDP payloads longer than 65527 bytes.  Therefore, endpoints

This is a long sentence that mixes singular and plural terms, for different concepts. I think this needs some editing to improve readability.

octets" in UDP). Clients MAY optimistically start sending proxied UDP packets before  <ins> receiving the response to its UDP proxying request.  However, implementors should note that such proxied packets may not be processed by the proxy if it responds to the request with a failure, or if the proxied packets are received by the proxy before the request. </ins> By virtue of the definition of the UDP header UDP, it is not possible to encode UDP payloads longer than 65527 bytes.  Therefore, endpoints


Template TEMPLATE with the variables "target_host" and "target_port". Examples are shown below: <del> The URI Template MUST be a level 3 template or lower.  The URI Template MUST be in absolute form, and MUST include non-empty scheme, authority and path components.  The path component of the URI Template MUST start with a slash "/".  All template variables MUST be within the path component of the URI.  The URI template MUST contain the two variables "target_host" and "target_port" and MAY contain other variables.  The URI Template MUST NOT contain any non-ASCII unicode characters and MUST only contain ASCII characters in the range 0x21-0x7E inclusive (note that percent-encoding is allowed). The URI Template MUST NOT use Reserved Expansion ("+" operator), Fragment Expansion ("#" operator), Label Expansion with Dot-Prefix, Path Segment Expansion with Slash-Prefix, nor Path-Style Parameter Expansion with Semicolon-Prefix.  If any of the requirements above are not met by a URI Template, the client MUST reject its configuration and fail the request without sending it to the proxy. </del>  Since the original HTTP CONNECT method allowed conveying the target host and port but not the scheme, proxy authority, path, nor query,

This single paragraph has ~150 words and about 10 normative requirements of the MUST / MUST NOT variety. Personally I find this quite a dense presentation of information. But I'll leave it up to your editorial discretion to fix or not.

Template TEMPLATE with the variables "target_host" and "target_port". Examples are shown below:  <ins> The following requirements apply to the URI Template: The URI Template MUST be a level 3 template or lower. The URI Template MUST be in absolute form, and MUST include non- empty scheme, authority and path components. The path component of the URI Template MUST start with a slash "/". All template variables MUST be within the path component of the URI. The URI template MUST contain the two variables "target_host" and "target_port" and MAY contain other variables. The URI Template MUST NOT contain any non-ASCII unicode characters and MUST only contain ASCII characters in the range 0x21-0x7E inclusive (note that percent-encoding is allowed). The URI Template MUST NOT use Reserved Expansion ("+" operator), Fragment Expansion ("#" operator), Label Expansion with Dot- Prefix, Path Segment Expansion with Slash-Prefix, nor Path-Style Parameter Expansion with Semicolon-Prefix. If any of the requirements above are not met by a URI Template, the client MUST reject its configuration and fail the request without sending it to the proxy. </ins> Since the original HTTP CONNECT method allowed conveying the target host and port but not the scheme, proxy authority, path, nor query,


it is possible for a context ID with the same numeric value to be simultaneously allocated in distinct requests, potentially with different semantics.  Context IDs MUST NOT be re-allocated within a <del> given HTTP namespace but MAY be allocated in any order.  Once allocated, any context ID can be used by both client and proxy - only allocation carries separate namespaces to avoid requiring synchronization. </del>  Registration is the action by which an endpoint informs its peer of the semantics and format of a given context ID.  This document does

Section 4, second paragrap: 'The context ID namespace is tied to a given HTTP request: it is possible for a context ID with the same numeric value to be simultaneously assigned different semantics in distinct requests, potentially with different semantics. Context IDs MUST NOT be re-allocated within a given HTTP namespace but MAY be allocated in any order.' I found this text initially confusing. I think what I was missing initially was a reminder that the HTTP datagram will be either in the communication context of the HTTP Request (HTTP 1.x) or the HTTP datagram will contain the quarter stream ID, and thus be in context. So an potential improvement here would be to add a clarification before this to remind that HTTP datagram will always be in context of a given HTTP request.
Fixed by
Section 4 last sentence 2 paragraph is: Why is there a "-"? Actually not sure what the second is supposed to say. Is there anything missing?
The dash has meaning similar to parentheses: it is equivalent to (see ). This parenthetical clause adds context to the main clause: allocation is separate but usage is not.
Do you have a suggestion for text that would be better?
I find the use of namespace in the quoted text unhelpful. You might editorialize this sentence a bit anyway to improve the clarity. Something like "Context ID allocation depends on restrictions to the use of even- and odd-numbered context IDs in order to avoid the need for synchronisation. However, once a context has been allocated, those restrictions no longer apply and context IDs can be used by any client or proxy, independent of who initially allocated them.
Lucas thanks that's much better! (I think this "allocation carries" wording confused me a bit)
:shipit:

it is possible for a context ID with the same numeric value to be simultaneously allocated in distinct requests, potentially with different semantics.  Context IDs MUST NOT be re-allocated within a  <ins> given HTTP namespace but MAY be allocated in any order.  The context ID allocation restrictions to the use of even-numbered and odd- numbered context IDs exist in order to avoid the need for synchronisation between endpoints.  However, once a context ID has been allocated, those restrictions do not apply to the use of the context ID: it can be used by any client or proxy, independent of which endpoint initially allocated it. </ins> Registration is the action by which an endpoint informs its peer of the semantics and format of a given context ID.  This document does


udp" uses the Capsule Protocol as defined in HTTP-DGRAM. Clients issue requests containing a "connect-udp" upgrade token to <del> initiate a UDP tunnel associated with a single HTTP stream.  The target of the tunnel is indicated by the client to the proxy via the "target_host" and "target_port" variables of the URI Template (see client-config).  If the request is successful, the proxy commits to converting received HTTP Datagrams into UDP packets and vice versa until the tunnel is closed.  Tunnels are commonly used to create an end-to-end virtual connection, which can then be secured using QUIC QUIC or another protocol running over UDP. </del>  When sending its UDP proxying request, the client SHALL perform URI Template expansion to determine the path and query of its request.

Yes that's much better. Thx
section 3 (http exchanges) has the following sentence and I don't understand the intention of this sentence: Tunnels are commonly used to create an end-to-end virtual connection, which can then be secured using [QUIC] or another protocol running over UDP. Is the intention of this sentence only to provide a definition of "tunnel"? In this case it should maybe be move into section 1.1? Or is there something else this sentence should tell me and I didn't get?
It's basically the equivalent to how HTTP/2 describes the CONNECT method URL
also uses the term "tunnel" to describe CONNECT.
Section 3 already describes in detail what it means by a UDP tunnel, can you clarify what's unclear?
The sentence just seems a bit out of context in this paragraph (maybe check the whole paragraph). If the intent is to just define the term tunnel, I think it would be more useful to move this sentence to section 1.1. If this sentence is trying to tell me more than defining what a UDP tunnel is, then I don't understand the sentence. So what is this sentence supposed to tell me?
The purpose of the text here is to inform implementations what the purpose of the HTTP exchange is (the tunnel is the purpose). That's important for HTTP implementers to understand why they would add support for it. E.g. If a server does not want to support that purpose, then it should reject it.
I totally didn't get that from this sentence. And I think it's still a bit misplaced. Maybe this should be a new paragraph...?
I'm not sure I see what's wrong here. Do you have a suggestion?
The single paragraph seems fine to me and in-keeping with the style that other HTTP documents use to speak about similar concepts. The only change I might suggest is to move the sentence "Tunnels are commonly used to create an end-to-end virtual connection, which can then be secured using [QUIC] or another protocol running over UDP." to immediately after the first sentence of the paragraph.
Thanks NAME I like that - wrote it up as

udp" uses the Capsule Protocol as defined in HTTP-DGRAM. Clients issue requests containing a "connect-udp" upgrade token to  <ins> initiate a UDP tunnel associated with a single HTTP stream.  Tunnels are commonly used to create an end-to-end virtual connection, which can then be secured using QUIC QUIC or another protocol running over UDP.  The target of the tunnel is indicated by the client to the proxy via the "target_host" and "target_port" variables of the URI Template (see client-config).  If the request is successful, the proxy commits to converting received HTTP Datagrams into UDP packets and vice versa until the tunnel is closed. </ins> When sending its UDP proxying request, the client SHALL perform URI Template expansion to determine the path and query of its request.


5. <del> When associated with UDP proxying request streams, the HTTP Datagram Payload field of HTTP Datagrams (see HTTP-DGRAM) has the format </del>  defined in dgram-format.  Note that when HTTP Datagrams are encoded using QUIC DATAGRAM frames, the Context ID field defined below directly follows the Quarter Stream ID field which is at the start of

I had to read the first sentence multiple time to parse it: When associated with UDP proxying request streams, the HTTP Datagram Payload field of HTTP Datagrams (see [HTTP-DGRAM]) has the format defined in [Figure 6]. I think turning the sentence around would make it slightly easier tor read: The HTTP Datagram Payload field of HTTP Datagrams (see [HTTP-DGRAM]) has the format defined in [Figure 6], when associated with streams of UDP proxying requests.
I think I find it easier to read the other way around
Or split the difference
that works too. I also found the term "UDP proxying request streams" a bit clumsy. but the new sentence works much better. Thanks!

5.  <ins> When HTTP Datagrams (see HTTP-DGRAM) are associated with UDP proxying request streams, the HTTP Datagram Payload field has the format </ins> defined in dgram-format.  Note that when HTTP Datagrams are encoded using QUIC DATAGRAM frames, the Context ID field defined below directly follows the Quarter Stream ID field which is at the start of


Therefore it needs to respond to the request without waiting for a packet from the target.  However, if the target_host is a DNS name, the proxy MUST perform DNS resolution before replying to the HTTP <del> request.  If DNS resolution fails, the proxy MUST fail the request and SHOULD send details using the Proxy-Status header field PROXY- STATUS. </del>  Proxies can use connected UDP sockets if their operating system supports them, as that allows the proxy to rely on the kernel to only

Section 3.1 mentions proxy handling requirements and notes a DNS failure SHOULD be communicated in the response using Proxy-Status. Is that the only case? Maybe it's worth mentioning that the header can be used for any other type of failure too.
It's linked to a SHOULD requirement
Fair enough. Let it be known that by this issue, NAME has volunteered to become Area Director.
I have been volunteered many times by other people, I don't think this one will change anything

Therefore it needs to respond to the request without waiting for a packet from the target.  However, if the target_host is a DNS name, the proxy MUST perform DNS resolution before replying to the HTTP  <ins> request.  If errors occur during this process (for example, a DNS resolution failure), the proxy MUST fail the request and SHOULD send details using the Proxy-Status header field PROXY-STATUS. </ins> Proxies can use connected UDP sockets if their operating system supports them, as that allows the proxy to rely on the kernel to only


3. This document defines the "connect-udp" HTTP Upgrade Token. "connect- <del> udp" uses the Capsule Protocol as defined in HTTP-DGRAM. </del>  Clients issue requests containing a "connect-udp" upgrade token to initiate a UDP tunnel associated with a single HTTP stream.  Tunnels

Section 3 "connect-udp" uses the Capsule Protocol as defined in [HTTP-DGRAM]. What does "uses" here mean? As there are situations where the Capsule Protocol and the Datagram Capsule defined in HTTP-DGRAM is not required to be used, it is not clear if it MUST be implemented and MAY be used?
It would be better to link specifically to URL associated request's data stream uses the Capsule Protocol. If they do so, that means that the contents of the associated request's data stream uses the following format ...
and possibly forward ref to https://ietf-wg-URL
And that might be clearer, assuming that the implementation requirement is clear in those section of the HTTP datagram spec.

3. This document defines the "connect-udp" HTTP Upgrade Token. "connect-  <ins> udp" uses the Capsule Protocol as defined in HTTP-DGRAM.  The format of HTTP Datagrams is defined in format. </ins> Clients issue requests containing a "connect-udp" upgrade token to initiate a UDP tunnel associated with a single HTTP stream.  Tunnels


the request SHALL include a single Host header field containing the origin of the UDP proxy. <del> the request SHALL include a single "Connection" header field with value "Upgrade" (note that this requirement is case-insensitive as per HTTP). </del>  the request SHALL include a single "Upgrade" header field with value "connect-udp".

"Upgrade" (note that this requirement is case-insensitive as per {{Section 7.6.1 of HTTP}}). "Single" implies that there can't be other values (at least in other header lines, and possibly this one). That's an inappropriate constraint.
Thanks for catching this oversight, fixing via .

the request SHALL include a single Host header field containing the origin of the UDP proxy.  <ins> the request SHALL include a "Connection" header field with value "Upgrade" (note that this requirement is case-insensitive as per HTTP). </ins> the request SHALL include a single "Upgrade" header field with value "connect-udp".


"Upgrade" (note that this requirement is case-insensitive as per HTTP). <del> the request SHALL include a single "Upgrade" header field with value "connect-udp". </del>  For example, if the client is configured with URI Template "https://proxy.example.org/.well-known/masque/

"connect-udp". "Single" implies that this mechanism is incompatible with any other upgrade mechanisms. If that's actually the case, it might be good to state so explicitly, rather than rely on this single word.
Thanks for catching this oversight. Similar to , this was not the intent. Fixing via .

"Upgrade" (note that this requirement is case-insensitive as per HTTP).  <ins> the request SHALL include an "Upgrade" header field with value "connect-udp". </ins> For example, if the client is configured with URI Template "https://proxy.example.org/.well-known/masque/


proxy deployments SHOULD offer service at this location if they need to interoperate with such clients. <del> Clients MAY interpret HTTP 400, 404, or 405 response codes as indications that the URI template is not correct.  Servers MUST NOT return these response codes if the request is well-formed and the URI matches a supported template. </del> 3. To allow negotiation of a tunnel for UDP over HTTP, this document

that the URI template is not correct. Servers MUST NOT return these response codes if the request is well-formed and the URI matches a supported template. Generally, we shy away from saying "server MUST NOT return x status code " in HTTP because there are situations where that's the best thing to do. For example, a MASQUE server could decide that sending a 404 is the best thing to do to hide the existence of a service from a given client.
That paragraph was added as part of , and thinking about it more it adds more confusion that clarity so I'm going to remove the paragraph in .
As the author of this paragraph, I'm concerned about its removal. The purpose of this text is to enable clients to figure out that the template they are using is not correct. This is especially important given the default template, which will almost always be incorrect. Without a rule like this, error codes are specific to a single URI (i.e. a single destination), and the client never knows if MASQUE might work for a different destination. It therefore has to try MASQUE for every destination (even though it will always fail if the template is wrong), or implement and tune a heuristic to abandon the use of MASQUE after failures with many destinations (which creates compatibility problems with MASQUE servers that serve limited destinations).
I'm assuming that by "the template is not correct" you mean "the client was configured with a different URI template than what the UDP proxy expects", please correct me if that's not the case. Since these error codes don't tell the client what URI template they should have used, the clients will not treat any errors in in a different way, so specifying error codes doesn't change any outcome here. This is very much a binary outcome, either it works or it doesn't. Clients will implement heuristics based on this binary response, not on error codes. As Mark points out, error codes can't be used for this purpose in HTTP.
No, HTTP error codes can distinguish between transient failures (e.g. 429), permanent/cacheable failures (e.g. 404), and even non-error results that some clients might not support (e.g. 307/8). The "Proxy-Status" header provides further detail, and is normatively recommended in this draft precisely because a binary response is insufficient. Some clients might indeed do that, but HTTP also has many minimal or nearly-stateless clients for whom heuristics of this kind would be difficult to implement well. Also, the draft provides no mention of any such heuristics, or guidance on how they ought to work. Mark suggested a SHOULD, which does not seem to be the same as "can't be used for this purpose".
What is the purpose of the MAY and SHOULD in the resulting paragraph? In what way would it improve interoperability?
My goal with this text was to enable clients to determine whether an HTTP CONNECT server also supports MASQUE. I'm not too picky about how that works, but there ought to be some way to do it. The "MAY" documents an approved way to do that, and implicitly threatens servers with incompatibility if they don't hold up their end. Whether we say "SHOULD" or "MUST" on the server side, the "MAY" for the client creates an effective normative requirement on servers. To be clear, my main concern here has been that server implementors will be tempted to represent NXDOMAIN or "No Route To Host" as 404, etc. That's a very logical mapping that would break a lot of client heuristics, but is not prohibited by anything in the draft.
I share that goal. The problem is that this gets tricky because in HTTP a server and an origin aren't the same thing. So my thought is that our best outcome is a two-pronged approach: keep CONNECT-UDP simple, browsers will re-use their "if QUIC breaks often, mark QUIC as broken and use TCP" approach publish something more formalized like draft-schwartz-masque-access-descriptions later to have something that solves the problem for more than just CONNECT-UDP I think the underlying realization here is that browsers will need to interop with servers that do the wrong thing via a simple "mark CONNECT-UDP as broken for this proxy" heuristic, and that once they do that, adding requirements on error codes doesn't gain anything that isn't already covered by Proxy-Status
I think that's reasonably likely to be true for browsers, but not all clients are browsers. Part of the problem is that the TCP fallback heuristic is more complicated than that. The client needs to fall back to TCP, see that TCP works, and only then attribute the failure as likely proxy-related. This is only possible if the proxy client is also the HTTP client, able to change the HTTP version. It does not work for system-level proxy layers, as they cannot control, or even track, UDP->TCP fallback. Ultimately, some heuristic somewhere will probably make it work, but we're creating waste and delay that could be avoided by giving some clear instructions about how to tell if this thing is a MASQUE proxy.
I agree, though I'm not aware of system proxy layers having plans to implement CONNECT-UDP just yet. By the time those happen we'll have a more formalized approach. We can't avoid waste and delay with SHOULDs and MAYs so might as well wait for the formalized solution to tackle that problem.
I suggested a SHOULD because saying that you MUST send a particular status code in a particular situation precludes sending other status codes that might be more relevant. It also encourages clients to equate seeing that status code to only that error condition, even when it might have been generated by another component. However, there's something else going on here -- If you want to say something about many resources, it's best to do so explicitly. While you can infer things about server state from a few HTTP status codes (e.g., 505), most are specific to the resource in question. Saying otherwise is changing the semantics of those status codes, and that isn't something this specification can do.

proxy deployments SHOULD offer service at this location if they need to interoperate with such clients.  3. To allow negotiation of a tunnel for UDP over HTTP, this document


successful UDP proxying responses also do not carry any message content. <del> Responses to UDP proxying requests are not cacheable. </del> 3.1. Upon receiving a UDP proxying request, the recipient UDP proxy

Try as we might, we can't retroactively place this requirement on the countless deployed caches on the Internet. Given that at least over HTTP/1.1 this mechanism uses GET, it might be better to specify that the GET response needs the appropriate caching metadata.
Good catch. That particular text came from back when we only used CONNECT, as that's defined as non-cacheable. Since defining how to cache Upgrade sounds like dragons holding footguns, I'm just going to remove this text via . That way we rely on existing HTTP documents to properly define how caching works.

successful UDP proxying responses also do not carry any message content.  3.1. Upon receiving a UDP proxying request, the recipient UDP proxy


3.1. <del> Upon receiving a UDP proxying request, the recipient UDP proxy extracts the "target_host" and "target_port" variables from the URI it has reconstructed from the request headers, and establishes a tunnel by directly opening a UDP socket to the requested target. </del>  Unlike TCP, UDP is connection-less.  The UDP proxy that opens the UDP socket has no way of knowing whether the destination is reachable.

Looking at the changes in the document I think I have picked up on another potential issue. Due to the discussion in URL I have to ask what happens if the client issues an Connect request over HTTP/2 that is then changed into an HTTP/1.1 request by an intermediate HTTP proxy in front of the actual MASQUE server. I don’t think this issue is discussed and what a MASQUE server does if it gets a CONNECT request with an Connect-UDP upgrade header.
In that scenario, the client will send: and the intermediary converting from HTTP/2 to HTTP/1.1 will convert that to: That works as expected. Are you saying there's a problem here?
Probably worth a mention in this spec, like CONNECT already does, that a proxy can forward CONNECT-UDP requests to a proxy it has configured. I don't think much more detail is required than that. Such a proxy needs to follow the normative requirements set out else where. Concerns about converting requests between HTTP versions are common and not terribly unique here.
That sounds like a worthwhile clarification. Tagging as editorial.
LGTM, parity with HTTP without compromising existing tone / style

3.1.  <ins> Upon receiving a UDP proxying request: if the recipient is configured to use another HTTP proxy, it will act as an intermediary: it forwards the request to another HTTP server.  Note that such intermediaries may need to reencode the request if they forward it using a version of HTTP that is different from the one used to receive it, as the request encoding differs by version (see below). otherwise, the recipient will act as a UDP proxy: it extracts the "target_host" and "target_port" variables from the URI it has reconstructed from the request headers, and establishes a tunnel by directly opening a UDP socket to the requested target. </ins> Unlike TCP, UDP is connection-less.  The UDP proxy that opens the UDP socket has no way of knowing whether the destination is reachable.


certainty that the inner traffic is congestion-controlled. If a client or UDP proxy with a connection containing a UDP proxying <del> request stream disables congestion control, it MUST NOT signal ECN support on that connection.  That is, it MUST mark all IP headers with the Not-ECT codepoint.  It MAY continue to report ECN feedback via ACK_ECN frames, as the peer may not have disabled congestion control. </del>  When the protocol running over UDP that is being proxied uses loss recovery (e.g., QUIC), and the underlying HTTP connection runs over

From AD Review: Expand the acronym and add a (normative!) reference.
I'm going to mark this editorial since it's just clarifying what ECN is, and I don't believe we've had any confusion on that point among working group members.
The second commit explicitly mentions the TCP ECN feedback mechanism, for completeness. And yes, this is editorial.

certainty that the inner traffic is congestion-controlled. If a client or UDP proxy with a connection containing a UDP proxying  <ins> request stream disables congestion control, it MUST NOT signal Explicit Congestion Notification (ECN) ECN support on that connection.  That is, it MUST mark all IP headers with the Not-ECT codepoint.  It MAY continue to report ECN feedback via QUIC ACK_ECN frames or the TCP "ECE" bit, as the peer may not have disabled congestion control. </ins> When the protocol running over UDP that is being proxied uses loss recovery (e.g., QUIC), and the underlying HTTP connection runs over


Since the original HTTP CONNECT method allowed conveying the target host and port but not the scheme, proxy authority, path, nor query, <del> there exist proxy configuration interfaces that only allow the user to configure the proxy host and the proxy port.  Client implementations of this specification that are constrained by such limitations MAY attempt to access UDP proxying capabilities using the default template, which is defined as: </del>  "https://$PROXY_HOST:$PROXY_PORT/.well-known/masque/ udp/{target_host}/{target_port}/" where $PROXY_HOST and $PROXY_PORT are the configured host and port of the UDP proxy respectively.  UDP

Nit from the AD review. Reading this sentence, it took me a moment to figure out if we were talking about config on the client or the on the proxy.

Since the original HTTP CONNECT method allowed conveying the target host and port but not the scheme, proxy authority, path, nor query,  <ins> there exist clients with proxy configuration interfaces that only allow the user to configure the proxy host and the proxy port. Client implementations of this specification that are constrained by such limitations MAY attempt to access UDP proxying capabilities using the default template, which is defined as: </ins> "https://$PROXY_HOST:$PROXY_PORT/.well-known/masque/ udp/{target_host}/{target_port}/" where $PROXY_HOST and $PROXY_PORT are the configured host and port of the UDP proxy respectively.  UDP


This document describes how to proxy UDP in HTTP, similar to how the HTTP CONNECT method allows proxying TCP in HTTP.  More specifically, <del> this document defines a protocol that allows HTTP clients to create a tunnel for UDP communications through an HTTP server that acts as a </del>  proxy. 1. While HTTP provides the CONNECT method (see HTTP) for creating a TCP <del> TCP tunnel to a proxy, it lacks a method for doing so for UDP UDP traffic. </del>  This document describes a protocol for tunnelling UDP to a server acting as a UDP-specific proxy over HTTP.  UDP tunnels are commonly containing the traffic's destination.  Clients generate those URLs using a URI Template TEMPLATE, as described in client-config. <del> This protocol supports all versions of HTTP by using HTTP Datagrams HTTP-DGRAM.  When using HTTP/2 H2 or HTTP/3 H3, it uses HTTP Extended CONNECT as described in EXT-CONNECT2 and EXT-CONNECT3.  When using HTTP/1.x H1, it uses HTTP Upgrade as defined in HTTP. </del>  1.1. tunnels use the Capsule Protocol (see HTTP-DGRAM) with HTTP Datagram in the format defined in format. <del> To initiate a UDP tunnel associated with a single HTTP stream, clients issue a request containing the "connect-udp" upgrade token. </del>  The target of the tunnel is indicated by the client to the UDP proxy via the "target_host" and "target_port" variables of the URI Template, see client-config.  If the request is successful, the UDP 4. <del> This protocol allows future extensions to exchange HTTP Datagrams which carry different semantics from UDP payloads.  Some of these extensions can augment UDP payloads with additional data, while others can exchange data that is completely separate from UDP payloads.  In order to accomplish this, all HTTP Datagrams associated with UDP Proxying request streams start with a context ID, see format. </del>  Context IDs are 62-bit integers (0 to 2

PR in response to Christer's GENART review -- Reviewer: Christer Holmberg Review result: Almost Ready I am the assigned Gen-ART reviewer for this draft. The General Area Review Team (Gen-ART) reviews all IETF documents being processed by the IESG for the IETF Chair. Please treat these comments just like any other last call comments. For more information, please see the FAQ at . Document: draft-ietf-masque-connect-udp-12 Reviewer: Christer Holmberg Review Date: 2022-05-28 IETF LC End Date: 2022-06-08 IESG Telechat date: Not scheduled for a telechat Summary: The document is well written, and easy to read. However, I do have some comments (mainly editorial) that I would like the authors to address. Major issues: N/A Minor issues: N/A Nits/editorial comments: GENERAL: QG1: The document contains a mix of "SHALL", "MUST", "SHALL NOT" and "MUST NOT", but I can't see any specifc pattern based on whether "SHALL (NOT)" or "MUST (NOT)" is used. ABSTRACT: QA1: The text says: "This document describes how to proxy UDP in HTTP," To me "proxy UDP in HTTP" sounds a little weird. Isn't "tunneling UDP over HTTP" more appropriate? That terminology is also used later in the document. (The same comment applies to "proxy TCP in HTTP") Section 1: Q11: The text says: "While HTTP provides the CONNECT method (see Section 9.3.6 of [HTTP]) for creating a TCP [TCP] tunnel to a proxy, it lacks a method for doing so for UDP [UDP] traffic." I suggest to remove the "it lacks..." part, because the following paragraph says that the document defines such method. Q12: The text says: "This protocol supports all versions of HTTP" I think the text should say which is the latest supported, as there is no guarantee future versions of HTTP will be supported. Section 1.1: Q111: The txt says: "Note that, when the HTTP version in use does not support multiplexing streams (such as HTTP/1.1), any reference to "stream" in this document represents the entire connection." I suggest to replace "Note that," with e.g., "In this document,", as in the paragraph above. Section 2: Q21: I suggest placing the example URIs after the requirements and procedures for creating the URL. Q22: The text says: "If the client detects that any of the requirements above are not met by a URI Template, the client MUST reject its configuration and fail the request without sending it to the UDP proxy. While clients SHOULD validate the requirements above, some clients MAY use a general-purpose URI Template implementation that lacks this specific validation." It sounds strange to say "MUST reject" while saying "SHOULD validate but MAY use a general-purpose URI Template implementation". I suggest to say "SHOULD validate the URI Template and reject it if it does not fulfil the requirements above". Section 3: Q31: (This comment might apply to other parts of the document too) The text says: "To initiate a UDP tunnel associated with a single HTTP stream, clients issue a request containing the "connect-udp" upgrade token." I suggest to refer to a single entity for the procedure, i.e., "client" instead of "clients". Section 3.1: Q311: The text says: "Upon receiving a UDP proxying request: if the recipient is configured to use another HTTP proxy, it will act as an intermediary: it forwards the request to another HTTP server. Note that such intermediaries may need to reencode the request if they forward it using a version of HTTP that is different from the one used to receive it, as the request encoding differs by version (see below). otherwise, the recipient will act as a UDP proxy: it extracts the "targethost" and "target_port" variables from the URI it has reconstructed from the request headers, and establishes a tunnel by directly opening a UDP socket to the requested target." It is unclear whether the rest of the Section text applies to both of these bullets, or only one of them. Also, the "(see below)" part in the first bullet refers to the following Sections, but it is unclear. If refering to another section, I suggest using explicit Section references instead of "below". Sections 3.2, 3.3, 3.4 and 3.5: I suggest to use sub-sections, with e.g., the following structure: HTTP/1.1 Usage Request Response HTTP/2 and HTTP/3 Usage Request Response Section 4: The text says: "This protocol..." What protocol? :) As this is the first sentence of the Section, please be specific.

This document describes how to proxy UDP in HTTP, similar to how the HTTP CONNECT method allows proxying TCP in HTTP.  More specifically,  <ins> this document defines a protocol that allows an HTTP client to create a tunnel for UDP communications through an HTTP server that acts as a </ins> proxy. 1. While HTTP provides the CONNECT method (see HTTP) for creating a TCP  <ins> TCP tunnel to a proxy, prior to this specification it lacked a method for doing so for UDP UDP traffic. </ins> This document describes a protocol for tunnelling UDP to a server acting as a UDP-specific proxy over HTTP.  UDP tunnels are commonly containing the traffic's destination.  Clients generate those URLs using a URI Template TEMPLATE, as described in client-config.  <ins> This protocol supports all existing versions of HTTP by using HTTP Datagrams HTTP-DGRAM.  When using HTTP/2 H2 or HTTP/3 H3, it uses HTTP Extended CONNECT as described in EXT-CONNECT2 and EXT-CONNECT3. When using HTTP/1.x H1, it uses HTTP Upgrade as defined in HTTP. </ins> 1.1. tunnels use the Capsule Protocol (see HTTP-DGRAM) with HTTP Datagram in the format defined in format.  <ins> To initiate a UDP tunnel associated with a single HTTP stream, a client issues a request containing the "connect-udp" upgrade token. </ins> The target of the tunnel is indicated by the client to the UDP proxy via the "target_host" and "target_port" variables of the URI Template, see client-config.  If the request is successful, the UDP 4.  <ins> The mechanism for proxying UDP in HTTP defined in this document allows future extensions to exchange HTTP Datagrams which carry different semantics from UDP payloads.  Some of these extensions can augment UDP payloads with additional data, while others can exchange data that is completely separate from UDP payloads.  In order to accomplish this, all HTTP Datagrams associated with UDP Proxying request streams start with a context ID, see format. </ins> Context IDs are 62-bit integers (0 to 2


8.2. <del> This document will request IANA to register "masque/udp" in the "Well-Known URIs" registry maintained at </del>  <<https://www.iana.org/assignments/well-known-uris>>.

As per registrations cannot contain a character so we register instead of
L602 still includes /udp, Is that intended?
Yeah my thinking was that we register and for now only define semantics for . A future document can tweak the related info line to also assign semantics to
I'm not a .well-known expert. My interpretation from mnot's suggestion was the prefix ends up as ".well-known/masque" and that the remainder is defined here as "/udp/{targethost}/{targetport}". Yes something else might come along and define other things to follow the prefix .well-known/masque but that can be deferred for later, and that spec needs to state all of its own rules. An alternative is that we expect everything after the prefix to behave in a similar way, I.e. .well-known/masque/{masquetype}/{targethost}/{target_port}. I don't know if that holds true.
From reading it appears that there is a lot of flexibility on how to organize additional path components so this appears OK to me, but I'll let NAME provide insights here
Yep, how you deal with what's "under" your registration is up to you. One option is to create a separate registry; another is to require additional values to update the registering RFC.

8.2.  <ins> This document will request IANA to register "masque" in the "Well- Known URIs" registry maintained at </ins> <<https://www.iana.org/assignments/well-known-uris>>.


servers that support UDP proxying ought to restrict its use to authenticated users.  Because the CONNECT method creates a TCP connection to the target, the target has to indicate its willingness to accept TCP connections by responding with a TCP SYN-ACK before the CONNECT proxy can send it protocol running over UDP would respond, and that would be interpreted as willingness to accept UDP by the UDP proxy. <del> UDP sockets for UDP proxying have a different lifetime than TCP sockets for CONNECT, therefore implementors would be well served to follow the advice in handling if they base their UDP proxying implementation on a preexisting implementation of CONNECT. </del> The security considerations described in HTTP-DGRAM also apply here. 8.

This PR is in response to . It improves the clarity of the Security Considerations section: the paragraph about willingness to receive needed an introductory sentence the paragraph about lifetimes no longer made sense and is removed
Look fine to me, posted some suggested editoiral tweaks you can take or leave Reviewer: Catherine Meadows Review result: Has Issues This draft describes a protocol for proxying UDP in HTTP, similar to the way in which HTTP CONNECT allows proxying TCP in HTTP. The Security Considerations Section, besides noting that the considerations identified in HTTP-DGRAM also apply, notes the necessity for authentication. It also notes the security issues (particularly, vulnerability to denial of service attacks)that arise from the fact that in UDP the target of a connection doesn’t have to indicate its willingness to accept a connection before a proxy sends data. It also discusses some issues that may arise from basing a UDP proxying implementation on a pre-existing implementation of the TCP CONNECT Protocol. I found a couple of minor issues, mainly having to do with clarity: Issue 1: I am confused by the last paragraph of the section, which runs as follows: UDP sockets for UDP proxying have a different lifetime than TCP sockets for CONNECT, therefore implementors would be well served to follow the advice in Section 3.1 if they base their UDP proxying implementation on a preexisting implementation of CONNECT. First of all, it’s not clear what the security implications of this are. This needs to be explained (or put elsewhere if there are no security implications). Secondly, it’s not clear what advice in Section 3.1 is relevant to this paragraph. Section 3.1 is mostly MUSTs and SHOULDs; I don’t see anything I would call advice. The paragraph needs to say more clearly what advice it is referring to. Issue 2: It is hard to draw a conclusion from the paragraph on DoS The first two sentences are clear. They state that the fact in the CONNECT method for TCP the target must indicate its willingness to receive data, while this is not the case for UDP, potentially makes it easier for UDP proxies implement denial of service attacks. However, I had trouble understanding the rest of the paragraph: However, in practice denial of service attacks target open TCP ports so the TCP SYN-ACK does not offer much protection in real scenarios. While a UDP proxy could potentially limit the number of UDP packets it is willing to forward until it has observed a response from the target, that is unlikely to provide any protection against denial of service attacks because such attacks target open UDP ports where the protocol running over UDP would respond, and that would be interpreted as willingness to accept UDP by the UDP proxy. I think that what this is intended to say is that because DoS attacks target open ports there is not much difference between TCP and UDP proxies as far as vulnerability to DoS is concerned. I would recommend saying this upfront. Then it would be easier to see how the two sentences above support that statement.

servers that support UDP proxying ought to restrict its use to authenticated users. <ins> UDP proxies have similar properties to TCP proxies when it comes to facilitating denial of service attacks.  In theory the stateful nature of TCP provides better protection than stateless UDP but in practice this provides negligible benefits when considering proxying. </ins> Because the CONNECT method creates a TCP connection to the target, the target has to indicate its willingness to accept TCP connections by responding with a TCP SYN-ACK before the CONNECT proxy can send it protocol running over UDP would respond, and that would be interpreted as willingness to accept UDP by the UDP proxy.  The security considerations described in HTTP-DGRAM also apply here. 8.


the request SHALL include an "Upgrade" header field with value "connect-udp".  For example, if the client is configured with URI Template "https://proxy.example.org/.well-known/masque/ udp/{target_host}/{target_port}/" and wishes to open a UDP proxying

This PR addresses the DISCUSS component of . The COMMENT component of that review will be addressed in a subsequent PR.
LGTMNice catch, thanks Zahed Zaheduzzaman Sarker has entered the following ballot position for draft-ietf-masque-connect-udp-14: Discuss When responding, please keep the subject line intact and reply to all email addresses included in the To and CC lines. (Feel free to cut this introductory paragraph, however.) Please refer to URL for more information about how to handle DISCUSS and COMMENT positions. The document, along with other ballot positions, can be found here: URL DISCUSS: This is I think simply a oversight but I am putting a discuss so that this certainly gets addressed before the document proceeds to the next stage. Section 3.2 does not say what happens when the requirements are not met. There must be guidance on what to do in that case like there are in section 3.3, 3.4 an 3.5. COMMENT: Thanks a lot for working on this specification. I think this specification will be very useful. I don't have other major issues other than mentioned in the discuss points. Below are some comments which I believe will improve the document if addressed. Section 3: s/pct-encoding/percent-encoding and would be good to add a reference to pct-encoding (URL) Section 3.1: it took a bit of time for me to understand if we are redefining the "intermediaries" here again. We have already described what is an intermediary in the context of this document. Hence, I would suggest that we just write - if the recipient is an intermediary, it forwards .... Section 3.1: what exactly "fail the request" means? is it only a notification to some waiting processes/methods or sending the error message or both? can we be more specific here? Section 5 : reference to the QUIC DATAGRAM frame would be nicer.Section 5 : it says - "Therefore, endpoints MUST NOT send HTTP Datagrams with a Payload field longer than 65527 using Context ID zero. An endpoint that receives a DATAGRAM capsule using Context ID zero whose Payload field is longer than 65527 MUST abort the stream. " I assume the HTTP Datagram and a DATAGRAM capsule is referring to the same thing, but this is confusing. Can use HTTP DATAGRAM in the second sentence as well? The DATAGRAM capsule kind of appeared in this section all on a sudden. In this section to me it seems HTTP DATAGRAM and DATAGRAM capsule is interchangeably used, if I am correct then I think it is worth mentioning this for the sake of better understanding. Section 5 : it says "If a UDP proxy knows it can only send out UDP packets of a certain length due to its underlying link MTU, it SHOULD discard incoming DATAGRAM capsules using Context ID zero whose Payload field is longer than that limit without buffering the capsule contents." It is not clear why "SHOULD" is used here? what are the other option the UDP proxy has in this case? Section 3.6: if this section should be removed then [STRUCT-FIELD] must not be in the normative section, actually should be removed from the references. Either at this stage of this document we can remove this section or we can add a note to remove normative reference when this section is removed.

the request SHALL include an "Upgrade" header field with value "connect-udp". <ins> A UDP proxying request that does not conform to these restrictions is malformed.  The recipient of such a malformed request MUST respond with an error, and SHOULD use the 400 (Bad Request) status code. </ins> For example, if the client is configured with URI Template "https://proxy.example.org/.well-known/masque/ udp/{target_host}/{target_port}/" and wishes to open a UDP proxying


control unless it has an out-of-band way of knowing with absolute certainty that the inner traffic is congestion-controlled.  When the protocol running over UDP that is being proxied uses loss recovery (e.g., QUIC), and the underlying HTTP connection runs over TCP, the proxied traffic will incur at least two nested loss recovery independently retransmit the same data.  To avoid this, HTTP/3 datagrams SHOULD be used.  10. There are significant risks in allowing arbitrary clients to

On a related note, the text in #performance talks about disabling congestion control on a "connection," but I believe this is actually a per-endpoint decision. (The client could easily have more information than the proxy on the tunneled connections).
Even if CONNECT-UDP has no explicit ECN support without an extension, there is ambiguity relating to copying of ECN bits between 'inner' and 'outer' datagrams. MASQUE is not strictly IP-in-IP, though it's close to it, so it's not clear if RFC 6040 applies. Nevertheless, I would propose the following principles: ECN markings on the MASQUE connection SHOULD NOT be copied to any resulting UDP datagrams sent by the proxy; they should apply to the MASQUE connection only. If MASQUE congestion control is disabled per section 9, it MUST mark all packets non-ECT. ECN markings on incoming UDP datagrams SHOULD NOT be copied to the IP headers of MASQUE packets that encapsulate them: upstream congestion should not affect the congestion state of the MASQUE connection. I'm happy to write a PR to that effect.
When using CONNECT-UDP without extensions, the server-facing UDP sockets on the proxy will not be configured to use ECN, so there will not be any ECN markings on the proxy-server path. In other words, ECN will not be in use, so do we need text about it? Adding text to clarify this sounds reasonable, but it probably should be generic to anything in the IP header.
The extensions explicitly concern markings on DATAGRAM frames in the inner connection. The server may very well be sending packets with ECT(0). With no extension, it will eventually stop, but nevertheless these shouldn’t appear in MASQUE IP headers.
Agreed. I'll take you up on your offer to write a PR then :)
Yes, I think that being clear that for this case the two legs needs to be kept seperate unless internal signalling is used on client to proxy leg to influence the external side setting and receiving of these values.
Thanks!

control unless it has an out-of-band way of knowing with absolute certainty that the inner traffic is congestion-controlled. <ins> If a client or proxy with a connection containing a CONNECT-UDP stream disables congestion control, it MUST NOT signal ECN support on that connection.  That is, it MUST mark all IP headers with the Not- ECT codepoint.  It MAY continue to report ECN feedback via ACK_ECN frames, as the peer may not have disabled congestion control. </ins> When the protocol running over UDP that is being proxied uses loss recovery (e.g., QUIC), and the underlying HTTP connection runs over TCP, the proxied traffic will incur at least two nested loss recovery independently retransmit the same data.  To avoid this, HTTP/3 datagrams SHOULD be used. <ins> 9.1. CONNECT-UDP does not create an IP-in-IP tunnel, so the guidance in RFC6040 about transferring ECN marks between inner and outer IP headers does not apply.  There is no inner IP header in CONNECT-UDP tunnels. Note that CONNECT-UDP clients do not have the ability in this specification to control the ECN codepoints on UDP packets the proxy sends to the server, nor can proxies communicate the markings of each UDP packet from server to proxy. A CONNECT-UDP proxy MUST ignore ECN bits in the IP header of UDP packets received from the server, and MUST set the ECN bits to Not- ECT on UDP packets it sends to the server.  These do not relate to the ECN markings of packets sent between client and proxy in any way. </ins> 10. There are significant risks in allowing arbitrary clients to


Since HTTP Datagrams require prior negotiation (for example, in HTTP/3 it is necessary to both send and receive the H3_DATAGRAM SETTINGS Parameter), clients MUST NOT send any HTTP Datagrams until <del> they have established support on a given connection.  If negotiation of HTTP Datagrams fails (for example if an HTTP/3 SETTINGS frame was received without the H3_DATAGRAM SETTINGS Parameter), the client MUST consider its CONNECT-UDP request as failed. </del>  The proxy that is creating the UDP socket to the destination responds to the CONNECT-UDP request with a 2xx (Successful) response.

In Sec. 4 it says: If negotiation of HTTP Datagrams fails (for example if an HTTP/3 SETTINGS frame was received without the H3_DATAGRAM SETTINGS Parameter), the client MUST consider its CONNECT-UDP request as failed. IIUC it is entirely possible to do CONNECT-UDP entirely with CAPSULE frames, so I don't see why a client should fail the attempt because the first hop is H/2 only, or whatever.
Thanks for writing this up. I think this is the right solution. I'll leave this open for some time to see if anyone else would like to comment. To add context: this text predates the creation of capsules, and now CONNECT-UDP works even if QUIC datagram frames aren't available. We'll want to pick a solution for URL though. If the H3_DATAGRAM setting also covers capsules we might still need this text. But for now we can remove it.

Since HTTP Datagrams require prior negotiation (for example, in HTTP/3 it is necessary to both send and receive the H3_DATAGRAM SETTINGS Parameter), clients MUST NOT send any HTTP Datagrams until  <ins> they have established support on a given connection. </ins> The proxy that is creating the UDP socket to the destination responds to the CONNECT-UDP request with a 2xx (Successful) response.


proxy MUST keep the socket open while the CONNECT-UDP stream is open. Proxies MAY choose to close sockets due to a period of inactivity, but they MUST close the CONNECT-UDP stream before closing the socket.  6.

This is partly related to URL but seems to fit its own issue. Let's assume a CONNECT-UDP request succeeds with a 2xx and a flow of datagrams is merrily exchanged. How do endpoints indicate they are done with the stream and associated flows? The spec doesn't really say anything. The main example I can think of is where a server decides to perform housekeeping on UDP connections (maybe as part of runtime garbage collection, or in reaction to the network stack throwing errors) after a 2xx was been sent. H3 CONNECT says ends the request stream (that is, the receive stream at the proxy enters the "Data Recvd" state), the proxy will set the FIN bit on its connection to the TCP server. When the proxy receives a packet with the FIN bit set, it will close the send stream that it sends to the client. TCP connections that remain half-closed in a single direction are not invalid, but are often handled poorly by servers, so clients SHOULD NOT close a stream for sending while they still expect to receive data from the target of the CONNECT. stream. A proxy treats any error in the TCP connection, which includes receiving a TCP segment with the RST bit set, as a stream error of type H3CONNECTERROR; see Section 8. Correspondingly, if a proxy detects an error with the stream or the QUIC connection, it MUST close the TCP connection. If the underlying TCP implementation permits it, the proxy SHOULD send a TCP segment with the RST bit set. Not all of that guidance directly translates but I think it would be helpful to set some expectations for endpoints wrt how stream read or write states might change during the lifetime of a CONNECT-UDP request - especially in the cases where no stream data is being exchanged.
I took "FIN or RESET = done" as a given, but it's worth stating. Proxy behavior will likely be identical in both the graceful and abrupt closure cases.

proxy MUST keep the socket open while the CONNECT-UDP stream is open. Proxies MAY choose to close sockets due to a period of inactivity, but they MUST close the CONNECT-UDP stream before closing the socket. <ins> If a proxy is notified by its operating system that its socket is no longer usable, it MUST close the CONNECT-UDP stream. </ins> 6.