| rfc9298.original | rfc9298.txt | |||
|---|---|---|---|---|
| MASQUE D. Schinazi | Internet Engineering Task Force (IETF) D. Schinazi | |||
| Internet-Draft Google LLC | Request for Comments: 9298 Google LLC | |||
| Intended status: Standards Track 17 June 2022 | Category: Standards Track August 2022 | |||
| Expires: 19 December 2022 | ISSN: 2070-1721 | |||
| Proxying UDP in HTTP | Proxying UDP in HTTP | |||
| draft-ietf-masque-connect-udp-15 | ||||
| Abstract | Abstract | |||
| This document describes how to proxy UDP in HTTP, similar to how the | This document describes how to proxy UDP in HTTP, similar to how the | |||
| HTTP CONNECT method allows proxying TCP in HTTP. More specifically, | HTTP CONNECT method allows proxying TCP in HTTP. More specifically, | |||
| this document defines a protocol that allows an HTTP client to create | 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 | a tunnel for UDP communications through an HTTP server that acts as a | |||
| proxy. | proxy. | |||
| About This Document | ||||
| This note is to be removed before publishing as an RFC. | ||||
| The latest revision of this draft can be found at https://ietf-wg- | ||||
| masque.github.io/draft-ietf-masque-connect-udp/draft-ietf-masque- | ||||
| connect-udp.html. Status information for this document may be found | ||||
| at https://datatracker.ietf.org/doc/draft-ietf-masque-connect-udp/. | ||||
| Discussion of this document takes place on the MASQUE Working Group | ||||
| mailing list (mailto:masque@ietf.org), which is archived at | ||||
| https://mailarchive.ietf.org/arch/browse/masque/. | ||||
| Source for this draft and an issue tracker can be found at | ||||
| https://github.com/ietf-wg-masque/draft-ietf-masque-connect-udp. | ||||
| Status of This Memo | Status of This Memo | |||
| This Internet-Draft is submitted in full conformance with the | This is an Internet Standards Track document. | |||
| provisions of BCP 78 and BCP 79. | ||||
| Internet-Drafts are working documents of the Internet Engineering | This document is a product of the Internet Engineering Task Force | |||
| Task Force (IETF). Note that other groups may also distribute | (IETF). It represents the consensus of the IETF community. It has | |||
| working documents as Internet-Drafts. The list of current Internet- | received public review and has been approved for publication by the | |||
| Drafts is at https://datatracker.ietf.org/drafts/current/. | Internet Engineering Steering Group (IESG). Further information on | |||
| Internet Standards is available in Section 2 of RFC 7841. | ||||
| Internet-Drafts are draft documents valid for a maximum of six months | Information about the current status of this document, any errata, | |||
| and may be updated, replaced, or obsoleted by other documents at any | and how to provide feedback on it may be obtained at | |||
| time. It is inappropriate to use Internet-Drafts as reference | https://www.rfc-editor.org/info/rfc9298. | |||
| material or to cite them other than as "work in progress." | ||||
| This Internet-Draft will expire on 19 December 2022. | ||||
| Copyright Notice | Copyright Notice | |||
| Copyright (c) 2022 IETF Trust and the persons identified as the | Copyright (c) 2022 IETF Trust and the persons identified as the | |||
| document authors. All rights reserved. | document authors. All rights reserved. | |||
| This document is subject to BCP 78 and the IETF Trust's Legal | This document is subject to BCP 78 and the IETF Trust's Legal | |||
| Provisions Relating to IETF Documents (https://trustee.ietf.org/ | Provisions Relating to IETF Documents | |||
| license-info) in effect on the date of publication of this document. | (https://trustee.ietf.org/license-info) in effect on the date of | |||
| Please review these documents carefully, as they describe your rights | publication of this document. Please review these documents | |||
| and restrictions with respect to this document. Code Components | carefully, as they describe your rights and restrictions with respect | |||
| extracted from this document must include Revised BSD License text as | to this document. Code Components extracted from this document must | |||
| described in Section 4.e of the Trust Legal Provisions and are | include Revised BSD License text as described in Section 4.e of the | |||
| provided without warranty as described in the Revised BSD License. | Trust Legal Provisions and are provided without warranty as described | |||
| in the Revised BSD License. | ||||
| Table of Contents | Table of Contents | |||
| 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 | 1. Introduction | |||
| 1.1. Conventions and Definitions . . . . . . . . . . . . . . . 3 | 1.1. Conventions and Definitions | |||
| 2. Client Configuration . . . . . . . . . . . . . . . . . . . . 3 | 2. Client Configuration | |||
| 3. Tunnelling UDP over HTTP . . . . . . . . . . . . . . . . . . 4 | 3. Tunneling UDP over HTTP | |||
| 3.1. UDP Proxy Handling . . . . . . . . . . . . . . . . . . . 5 | 3.1. UDP Proxy Handling | |||
| 3.2. HTTP/1.1 Request . . . . . . . . . . . . . . . . . . . . 6 | 3.2. HTTP/1.1 Request | |||
| 3.3. HTTP/1.1 Response . . . . . . . . . . . . . . . . . . . . 7 | 3.3. HTTP/1.1 Response | |||
| 3.4. HTTP/2 and HTTP/3 Requests . . . . . . . . . . . . . . . 8 | 3.4. HTTP/2 and HTTP/3 Requests | |||
| 3.5. HTTP/2 and HTTP/3 Responses . . . . . . . . . . . . . . . 9 | 3.5. HTTP/2 and HTTP/3 Responses | |||
| 3.6. Note About Draft Versions . . . . . . . . . . . . . . . . 9 | 4. Context Identifiers | |||
| 4. Context Identifiers . . . . . . . . . . . . . . . . . . . . . 9 | 5. HTTP Datagram Payload Format | |||
| 5. HTTP Datagram Payload Format . . . . . . . . . . . . . . . . 10 | 6. Performance Considerations | |||
| 6. Performance Considerations . . . . . . . . . . . . . . . . . 12 | 6.1. MTU Considerations | |||
| 6.1. MTU Considerations . . . . . . . . . . . . . . . . . . . 12 | 6.2. Tunneling of ECN Marks | |||
| 6.2. Tunneling of ECN Marks . . . . . . . . . . . . . . . . . 13 | 7. Security Considerations | |||
| 7. Security Considerations . . . . . . . . . . . . . . . . . . . 13 | 8. IANA Considerations | |||
| 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 14 | 8.1. HTTP Upgrade Token | |||
| 8.1. HTTP Upgrade Token . . . . . . . . . . . . . . . . . . . 14 | 8.2. Well-Known URI | |||
| 8.2. Well-Known URI . . . . . . . . . . . . . . . . . . . . . 14 | 9. References | |||
| 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 14 | 9.1. Normative References | |||
| 9.1. Normative References . . . . . . . . . . . . . . . . . . 14 | 9.2. Informative References | |||
| 9.2. Informative References . . . . . . . . . . . . . . . . . 16 | Acknowledgments | |||
| Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 17 | Author's Address | |||
| Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 18 | ||||
| 1. Introduction | 1. Introduction | |||
| While HTTP provides the CONNECT method (see Section 9.3.6 of [HTTP]) | While HTTP provides the CONNECT method (see Section 9.3.6 of [HTTP]) | |||
| for creating a TCP [TCP] tunnel to a proxy, prior to this | for creating a TCP [TCP] tunnel to a proxy, it lacked a method for | |||
| specification it lacked a method for doing so for UDP [UDP] traffic. | doing so for UDP [UDP] traffic prior to this specification. | |||
| This document describes a protocol for tunnelling UDP to a server | This document describes a protocol for tunneling UDP to a server | |||
| acting as a UDP-specific proxy over HTTP. UDP tunnels are commonly | acting as a UDP-specific proxy over HTTP. UDP tunnels are commonly | |||
| used to create an end-to-end virtual connection, which can then be | used to create an end-to-end virtual connection, which can then be | |||
| secured using QUIC [QUIC] or another protocol running over UDP. | secured using QUIC [QUIC] or another protocol running over UDP. | |||
| Unlike CONNECT, the UDP proxy itself is identified with an absolute | Unlike the HTTP CONNECT method, the UDP proxy itself is identified | |||
| URL containing the traffic's destination. Clients generate those | with an absolute URL containing the traffic's destination. Clients | |||
| URLs using a URI Template [TEMPLATE], as described in Section 2. | generate those URLs using a URI Template [TEMPLATE], as described in | |||
| Section 2. | ||||
| This protocol supports all existing versions of HTTP by using HTTP | This protocol supports all existing versions of HTTP by using HTTP | |||
| Datagrams [HTTP-DGRAM]. When using HTTP/2 [HTTP/2] or HTTP/3 | Datagrams [HTTP-DGRAM]. When using HTTP/2 [HTTP/2] or HTTP/3 | |||
| [HTTP/3], it uses HTTP Extended CONNECT as described in | [HTTP/3], it uses HTTP Extended CONNECT as described in | |||
| [EXT-CONNECT2] and [EXT-CONNECT3]. When using HTTP/1.x [HTTP/1.1], | [EXT-CONNECT2] and [EXT-CONNECT3]. When using HTTP/1.x [HTTP/1.1], | |||
| it uses HTTP Upgrade as defined in Section 7.8 of [HTTP]. | it uses HTTP Upgrade as defined in Section 7.8 of [HTTP]. | |||
| 1.1. Conventions and Definitions | 1.1. Conventions and Definitions | |||
| The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | |||
| "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | |||
| "OPTIONAL" in this document are to be interpreted as described in | "OPTIONAL" in this document are to be interpreted as described in | |||
| BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all | BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all | |||
| capitals, as shown here. | capitals, as shown here. | |||
| In this document, we use the term "UDP proxy" to refer to the HTTP | In this document, we use the term "UDP proxy" to refer to the HTTP | |||
| server that acts upon the client's UDP tunnelling request to open a | server that acts upon the client's UDP tunneling request to open a | |||
| UDP socket to a target server, and generates the response to this | UDP socket to a target server and that generates the response to this | |||
| request. If there are HTTP intermediaries (as defined in Section 3.7 | request. If there are HTTP intermediaries (as defined in Section 3.7 | |||
| of [HTTP]) between the client and the UDP proxy, those are referred | of [HTTP]) between the client and the UDP proxy, those are referred | |||
| to as "intermediaries" in this document. | to as "intermediaries" in this document. | |||
| Note that, when the HTTP version in use does not support multiplexing | Note that, when the HTTP version in use does not support multiplexing | |||
| streams (such as HTTP/1.1), any reference to "stream" in this | streams (such as HTTP/1.1), any reference to "stream" in this | |||
| document represents the entire connection. | document represents the entire connection. | |||
| 2. Client Configuration | 2. Client Configuration | |||
| skipping to change at page 4, line 5 ¶ | skipping to change at line 128 ¶ | |||
| https://example.org/.well-known/masque/udp/{target_host}/{target_port}/ | https://example.org/.well-known/masque/udp/{target_host}/{target_port}/ | |||
| https://proxy.example.org:4443/masque?h={target_host}&p={target_port} | https://proxy.example.org:4443/masque?h={target_host}&p={target_port} | |||
| https://proxy.example.org:4443/masque{?target_host,target_port} | https://proxy.example.org:4443/masque{?target_host,target_port} | |||
| Figure 1: URI Template Examples | Figure 1: URI Template Examples | |||
| The following requirements apply to the URI Template: | The following requirements apply to the URI Template: | |||
| * The URI Template MUST be a level 3 template or lower. | * The URI Template MUST be a level 3 template or lower. | |||
| * The URI Template MUST be in absolute form, and MUST include non- | * The URI Template MUST be in absolute form and MUST include non- | |||
| empty scheme, authority and path components. | empty scheme, authority, and path components. | |||
| * The path component of the URI Template MUST start with a slash | * The path component of the URI Template MUST start with a slash | |||
| "/". | ("/"). | |||
| * All template variables MUST be within the path or query components | * All template variables MUST be within the path or query components | |||
| of the URI. | of the URI. | |||
| * The URI template MUST contain the two variables "target_host" and | * The URI Template MUST contain the two variables "target_host" and | |||
| "target_port" and MAY contain other variables. | "target_port" and MAY contain other variables. | |||
| * The URI Template MUST NOT contain any non-ASCII unicode characters | * The URI Template MUST NOT contain any non-ASCII Unicode characters | |||
| and MUST only contain ASCII characters in the range 0x21-0x7E | and MUST only contain ASCII characters in the range 0x21-0x7E | |||
| inclusive (note that percent-encoding is allowed; see Section 2.1 | inclusive (note that percent-encoding is allowed; see Section 2.1 | |||
| of [URI]). | of [URI]). | |||
| * The URI Template MUST NOT use Reserved Expansion ("+" operator), | * The URI Template MUST NOT use Reserved Expansion ("+" operator), | |||
| Fragment Expansion ("#" operator), Label Expansion with Dot- | Fragment Expansion ("#" operator), Label Expansion with Dot- | |||
| Prefix, Path Segment Expansion with Slash-Prefix, nor Path-Style | Prefix, Path Segment Expansion with Slash-Prefix, nor Path-Style | |||
| Parameter Expansion with Semicolon-Prefix. | Parameter Expansion with Semicolon-Prefix. | |||
| Clients SHOULD validate the requirements above; however, clients MAY | Clients SHOULD validate the requirements above; however, clients MAY | |||
| use a general-purpose URI Template implementation that lacks this | use a general-purpose URI Template implementation that lacks this | |||
| specific validation. If a client detects that any of the | specific validation. If a client detects that any of the | |||
| requirements above are not met by a URI Template, the client MUST | requirements above are not met by a URI Template, the client MUST | |||
| reject its configuration and abort the request without sending it to | reject its configuration and abort the request without sending it to | |||
| the UDP proxy. | the UDP proxy. | |||
| Since the original HTTP CONNECT method allowed conveying the target | The original HTTP CONNECT method allowed for the conveyance of the | |||
| host and port but not the scheme, proxy authority, path, nor query, | target host and port, but not the scheme, proxy authority, path, or | |||
| there exist clients with proxy configuration interfaces that only | query. Thus, clients with proxy configuration interfaces that only | |||
| allow the user to configure the proxy host and the proxy port. | allow the user to configure the proxy host and the proxy port exist. | |||
| Client implementations of this specification that are constrained by | Client implementations of this specification that are constrained by | |||
| such limitations MAY attempt to access UDP proxying capabilities | such limitations MAY attempt to access UDP proxying capabilities | |||
| using the default template, which is defined as: | using the default template, which is defined as | |||
| "https://$PROXY_HOST:$PROXY_PORT/.well-known/masque/ | "https://$PROXY_HOST:$PROXY_PORT/.well-known/masque/ | |||
| udp/{target_host}/{target_port}/" where $PROXY_HOST and $PROXY_PORT | udp/{target_host}/{target_port}/", where $PROXY_HOST and $PROXY_PORT | |||
| are the configured host and port of the UDP proxy respectively. UDP | are the configured host and port of the UDP proxy, respectively. UDP | |||
| proxy deployments SHOULD offer service at this location if they need | proxy deployments SHOULD offer service at this location if they need | |||
| to interoperate with such clients. | to interoperate with such clients. | |||
| 3. Tunnelling UDP over HTTP | 3. Tunneling UDP over HTTP | |||
| To allow negotiation of a tunnel for UDP over HTTP, this document | To allow negotiation of a tunnel for UDP over HTTP, this document | |||
| defines the "connect-udp" HTTP Upgrade Token. The resulting UDP | defines the "connect-udp" HTTP upgrade token. The resulting UDP | |||
| tunnels use the Capsule Protocol (see Section 3.2 of [HTTP-DGRAM]) | tunnels use the Capsule Protocol (see Section 3.2 of [HTTP-DGRAM]) | |||
| with HTTP Datagrams in the format defined in Section 5. | with HTTP Datagrams in the format defined in Section 5. | |||
| To initiate a UDP tunnel associated with a single HTTP stream, a | To initiate a UDP tunnel associated with a single HTTP stream, a | |||
| client issues a request containing the "connect-udp" upgrade token. | client issues a request containing the "connect-udp" upgrade token. | |||
| The target of the tunnel is indicated by the client to the UDP proxy | 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 | via the "target_host" and "target_port" variables of the URI | |||
| Template, see Section 2. If the request is successful, the UDP proxy | Template; see Section 2. | |||
| commits to converting received HTTP Datagrams into UDP packets and | ||||
| vice versa until the tunnel is closed. | "target_host" supports using DNS names, IPv6 literals and IPv4 | |||
| literals. Note that IPv6 scoped addressing zone identifiers are not | ||||
| supported. Using the terms IPv6address, IPv4address, reg-name, and | ||||
| port from [URI], the "target_host" and "target_port" variables MUST | ||||
| adhere to the format in Figure 2, using notation from [ABNF]. | ||||
| Additionally: | ||||
| * both the "target_host" and "target_port" variables MUST NOT be | ||||
| empty. | ||||
| * if "target_host" contains an IPv6 literal, the colons (":") MUST | ||||
| be percent-encoded. For example, if the target host is | ||||
| "2001:db8::42", it will be encoded in the URI as | ||||
| "2001%3Adb8%3A%3A42". | ||||
| * "target_port" MUST represent an integer between 1 and 65535 | ||||
| inclusive. | ||||
| target_host = IPv6address / IPv4address / reg-name | ||||
| target_port = port | ||||
| Figure 2: URI Template Variable Format | ||||
| When sending its UDP proxying request, the client SHALL perform URI | When sending its UDP proxying request, the client SHALL perform URI | |||
| Template expansion to determine the path and query of its request. | Template expansion to determine the path and query of its request. | |||
| target_host supports using DNS names, IPv6 literals and IPv4 | ||||
| literals. Note that IPv6 scoped addressing zone identifiers are not | If the request is successful, the UDP proxy commits to converting | |||
| supported. Also note that this URI Template expansion requires using | received HTTP Datagrams into UDP packets, and vice versa, until the | |||
| percent-encoding, so for example if the target_host is | tunnel is closed. | |||
| "2001:db8::42", it will be encoded in the URI as | ||||
| "2001%3Adb8%3A%3A42". | ||||
| By virtue of the definition of the Capsule Protocol (see Section 3.2 | By virtue of the definition of the Capsule Protocol (see Section 3.2 | |||
| of [HTTP-DGRAM]), UDP proxying requests do not carry any message | of [HTTP-DGRAM]), UDP proxying requests do not carry any message | |||
| content. Similarly, successful UDP proxying responses also do not | content. Similarly, successful UDP proxying responses also do not | |||
| carry any message content. | carry any message content. | |||
| 3.1. UDP Proxy Handling | 3.1. UDP Proxy Handling | |||
| Upon receiving a UDP proxying request: | Upon receiving a UDP proxying request: | |||
| * if the recipient is configured to use another HTTP proxy, it will | * if the recipient is configured to use another HTTP proxy, it will | |||
| act as an intermediary: it forwards the request to another HTTP | act as an intermediary by forwarding the request to another HTTP | |||
| server. Note that such intermediaries may need to reencode the | server. Note that such intermediaries may need to re-encode the | |||
| request if they forward it using a version of HTTP that is | request if they forward it using a version of HTTP that is | |||
| different from the one used to receive it, as the request encoding | different from the one used to receive it, as the request encoding | |||
| differs by version (see below). | differs by version (see below). | |||
| * otherwise, the recipient will act as a UDP proxy: it extracts the | * otherwise, the recipient will act as a UDP proxy. It extracts the | |||
| "target_host" and "target_port" variables from the URI it has | "target_host" and "target_port" variables from the URI it has | |||
| reconstructed from the request headers, and establishes a tunnel | reconstructed from the request headers, decodes their percent- | |||
| by directly opening a UDP socket to the requested target. | encoding, and establishes a tunnel by directly opening a UDP | |||
| socket to the requested target. | ||||
| Unlike TCP, UDP is connection-less. The UDP proxy that opens the UDP | Unlike TCP, UDP is connectionless. The UDP proxy that opens the UDP | |||
| socket has no way of knowing whether the destination is reachable. | socket has no way of knowing whether the destination is reachable. | |||
| Therefore, it needs to respond to the request without waiting for a | 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, | packet from the target. However, if the "target_host" is a DNS name, | |||
| the UDP proxy MUST perform DNS resolution before replying to the HTTP | the UDP proxy MUST perform DNS resolution before replying to the HTTP | |||
| request. If errors occur during this process, the UDP proxy MUST | request. If errors occur during this process, the UDP proxy MUST | |||
| reject the request and SHOULD send details using an appropriate | reject the request and SHOULD send details using an appropriate | |||
| "Proxy-Status" header field [PROXY-STATUS] (for example, if DNS | Proxy-Status header field [PROXY-STATUS]. For example, if DNS | |||
| resolution returns an error, the proxy can use the dns_error Proxy | resolution returns an error, the proxy can use the dns_error Proxy | |||
| Error Type from Section 2.3.2 of [PROXY-STATUS]). | Error Type from Section 2.3.2 of [PROXY-STATUS]. | |||
| UDP proxies can use connected UDP sockets if their operating system | UDP proxies can use connected UDP sockets if their operating system | |||
| supports them, as that allows the UDP proxy to rely on the kernel to | supports them, as that allows the UDP proxy to rely on the kernel to | |||
| only send it UDP packets that match the correct 5-tuple. If the UDP | only send it UDP packets that match the correct 5-tuple. If the UDP | |||
| proxy uses a non-connected socket, it MUST validate the IP source | proxy uses a non-connected socket, it MUST validate the IP source | |||
| address and UDP source port on received packets to ensure they match | address and UDP source port on received packets to ensure they match | |||
| the client's request. Packets that do not match MUST be discarded by | the client's request. Packets that do not match MUST be discarded by | |||
| the UDP proxy. | the UDP proxy. | |||
| The lifetime of the socket is tied to the request stream. The UDP | The lifetime of the socket is tied to the request stream. The UDP | |||
| proxy MUST keep the socket open while the request stream is open. If | proxy MUST keep the socket open while the request stream is open. If | |||
| a UDP proxy is notified by its operating system that its socket is no | a UDP proxy is notified by its operating system that its socket is no | |||
| longer usable (for example, this can happen when an ICMP "Destination | longer usable, it MUST close the request stream. For example, this | |||
| Unreachable" message is received, see Section 3.1 of [ICMP6]), it | can happen when an ICMP Destination Unreachable message is received; | |||
| MUST close the request stream. UDP proxies MAY choose to close | see Section 3.1 of [ICMP6]. UDP proxies MAY choose to close sockets | |||
| sockets due to a period of inactivity, but they MUST close the | due to a period of inactivity, but they MUST close the request stream | |||
| request stream when closing the socket. UDP proxies that close | when closing the socket. UDP proxies that close sockets after a | |||
| sockets after a period of inactivity SHOULD NOT use a period lower | period of inactivity SHOULD NOT use a period lower than two minutes; | |||
| than two minutes, see Section 4.3 of [BEHAVE]. | see Section 4.3 of [BEHAVE]. | |||
| A successful response (as defined in Section 3.3 and Section 3.5) | A successful response (as defined in Sections 3.3 and 3.5) indicates | |||
| indicates that the UDP proxy has opened a socket to the requested | that the UDP proxy has opened a socket to the requested target and is | |||
| target and is willing to proxy UDP payloads. Any response other than | willing to proxy UDP payloads. Any response other than a successful | |||
| a successful response indicates that the request has failed, and the | response indicates that the request has failed; thus, the client MUST | |||
| client MUST therefore abort the request. | abort the request. | |||
| UDP proxies MUST NOT introduce fragmentation at the IP layer when | UDP proxies MUST NOT introduce fragmentation at the IP layer when | |||
| forwarding HTTP Datagrams onto a UDP socket; overly large datagrams | forwarding HTTP Datagrams onto a UDP socket; overly large datagrams | |||
| are silently dropped. In IPv4, the Don't Fragment (DF) bit MUST be | are silently dropped. In IPv4, the Don't Fragment (DF) bit MUST be | |||
| set if possible, to prevent fragmentation on the path. Future | set, if possible, to prevent fragmentation on the path. Future | |||
| extensions MAY remove these requirements. | extensions MAY remove these requirements. | |||
| Implementers of UDP proxies will benefit from reading the guidance in | Implementers of UDP proxies will benefit from reading the guidance in | |||
| [UDP-USAGE]. | [UDP-USAGE]. | |||
| 3.2. HTTP/1.1 Request | 3.2. HTTP/1.1 Request | |||
| When using HTTP/1.1 [HTTP/1.1], a UDP proxying request will meet the | When using HTTP/1.1 [HTTP/1.1], a UDP proxying request will meet the | |||
| following requirements: | following requirements: | |||
| * the method SHALL be "GET". | * the method SHALL be "GET". | |||
| * the request SHALL include a single "Host" header field containing | * the request SHALL include a single Host header field containing | |||
| the origin of the UDP proxy. | the origin of the UDP proxy. | |||
| * the request SHALL include a "Connection" header field with value | * the request SHALL include a Connection header field with value | |||
| "Upgrade" (note that this requirement is case-insensitive as per | "Upgrade" (note that this requirement is case-insensitive as per | |||
| Section 7.6.1 of [HTTP]). | Section 7.6.1 of [HTTP]). | |||
| * the request SHALL include an "Upgrade" header field with value | * the request SHALL include an Upgrade header field with value | |||
| "connect-udp". | "connect-udp". | |||
| A UDP proxying request that does not conform to these restrictions is | A UDP proxying request that does not conform to these restrictions is | |||
| malformed. The recipient of such a malformed request MUST respond | malformed. The recipient of such a malformed request MUST respond | |||
| with an error, and SHOULD use the 400 (Bad Request) status code. | with an error and SHOULD use the 400 (Bad Request) status code. | |||
| For example, if the client is configured with URI Template | For example, if the client is configured with URI Template | |||
| "https://example.org/.well-known/masque/ | "https://example.org/.well-known/masque/ | |||
| udp/{target_host}/{target_port}/" and wishes to open a UDP proxying | udp/{target_host}/{target_port}/" and wishes to open a UDP proxying | |||
| tunnel to target 192.0.2.6:443, it could send the following request: | tunnel to target 192.0.2.6:443, it could send the following request: | |||
| GET https://example.org/.well-known/masque/udp/192.0.2.6/443/ HTTP/1.1 | GET https://example.org/.well-known/masque/udp/192.0.2.6/443/ HTTP/1.1 | |||
| Host: example.org | Host: example.org | |||
| Connection: Upgrade | Connection: Upgrade | |||
| Upgrade: connect-udp | Upgrade: connect-udp | |||
| Capsule-Protocol: ?1 | Capsule-Protocol: ?1 | |||
| Figure 2: Example HTTP/1.1 Request | Figure 3: Example HTTP/1.1 Request | |||
| In HTTP/1.1, this protocol uses the GET method to mimic the design of | In HTTP/1.1, this protocol uses the GET method to mimic the design of | |||
| the WebSocket Protocol [WEBSOCKET]. | the WebSocket Protocol [WEBSOCKET]. | |||
| 3.3. HTTP/1.1 Response | 3.3. HTTP/1.1 Response | |||
| The UDP proxy SHALL indicate a successful response by replying with | The UDP proxy SHALL indicate a successful response by replying with | |||
| the following requirements: | the following requirements: | |||
| * the HTTP status code on the response SHALL be 101 (Switching | * the HTTP status code on the response SHALL be 101 (Switching | |||
| Protocols). | Protocols). | |||
| * the reponse SHALL include a "Connection" header field with value | * the response SHALL include a Connection header field with value | |||
| "Upgrade" (note that this requirement is case-insensitive as per | "Upgrade" (note that this requirement is case-insensitive as per | |||
| Section 7.6.1 of [HTTP]). | Section 7.6.1 of [HTTP]). | |||
| * the response SHALL include a single "Upgrade" header field with | * the response SHALL include a single Upgrade header field with | |||
| value "connect-udp". | value "connect-udp". | |||
| * the response SHALL meet the requirements of HTTP responses that | * the response SHALL meet the requirements of HTTP responses that | |||
| start the Capsule Protocol; see Section 3.2 of [HTTP-DGRAM]. | start the Capsule Protocol; see Section 3.2 of [HTTP-DGRAM]. | |||
| If any of these requirements are not met, the client MUST treat this | If any of these requirements are not met, the client MUST treat this | |||
| proxying attempt as failed and abort the connection. | proxying attempt as failed and abort the connection. | |||
| For example, the UDP proxy could respond with: | For example, the UDP proxy could respond with: | |||
| HTTP/1.1 101 Switching Protocols | HTTP/1.1 101 Switching Protocols | |||
| Connection: Upgrade | Connection: Upgrade | |||
| Upgrade: connect-udp | Upgrade: connect-udp | |||
| Capsule-Protocol: ?1 | Capsule-Protocol: ?1 | |||
| Figure 3: Example HTTP/1.1 Response | Figure 4: Example HTTP/1.1 Response | |||
| 3.4. HTTP/2 and HTTP/3 Requests | 3.4. HTTP/2 and HTTP/3 Requests | |||
| When using HTTP/2 [HTTP/2] or HTTP/3 [HTTP/3], UDP proxying requests | When using HTTP/2 [HTTP/2] or HTTP/3 [HTTP/3], UDP proxying requests | |||
| use Extended CONNECT. This requires that servers send an HTTP | use HTTP Extended CONNECT. This requires that servers send an HTTP | |||
| Setting as specified in [EXT-CONNECT2] and [EXT-CONNECT3], and that | Setting as specified in [EXT-CONNECT2] and [EXT-CONNECT3] and that | |||
| requests use HTTP pseudo-header fields with the following | requests use HTTP pseudo-header fields with the following | |||
| requirements: | requirements: | |||
| * The ":method" pseudo-header field SHALL be "CONNECT". | * The :method pseudo-header field SHALL be "CONNECT". | |||
| * The ":protocol" pseudo-header field SHALL be "connect-udp". | * The :protocol pseudo-header field SHALL be "connect-udp". | |||
| * The ":authority" pseudo-header field SHALL contain the authority | * The :authority pseudo-header field SHALL contain the authority of | |||
| of the UDP proxy. | the UDP proxy. | |||
| * The ":path" and ":scheme" pseudo-header fields SHALL NOT be empty. | * The :path and :scheme pseudo-header fields SHALL NOT be empty. | |||
| Their values SHALL contain the scheme and path from the URI | Their values SHALL contain the scheme and path from the URI | |||
| Template after the URI template expansion process has been | Template after the URI Template expansion process has been | |||
| completed. | completed. | |||
| A UDP proxying request that does not conform to these restrictions is | A UDP proxying request that does not conform to these restrictions is | |||
| malformed (see Section 8.1.1 of [HTTP/2] and Section 4.1.2 of | malformed (see Section 8.1.1 of [HTTP/2] and Section 4.1.2 of | |||
| [HTTP/3]). | [HTTP/3]). | |||
| For example, if the client is configured with URI Template | For example, if the client is configured with URI Template | |||
| "https://example.org/.well-known/masque/ | "https://example.org/.well-known/masque/ | |||
| udp/{target_host}/{target_port}/" and wishes to open a UDP proxying | udp/{target_host}/{target_port}/" and wishes to open a UDP proxying | |||
| tunnel to target 192.0.2.6:443, it could send the following request: | tunnel to target 192.0.2.6:443, it could send the following request: | |||
| HEADERS | HEADERS | |||
| :method = CONNECT | :method = CONNECT | |||
| :protocol = connect-udp | :protocol = connect-udp | |||
| :scheme = https | :scheme = https | |||
| :path = /.well-known/masque/udp/192.0.2.6/443/ | :path = /.well-known/masque/udp/192.0.2.6/443/ | |||
| :authority = example.org | :authority = example.org | |||
| capsule-protocol = ?1 | capsule-protocol = ?1 | |||
| Figure 4: Example HTTP/2 Request | Figure 5: Example HTTP/2 Request | |||
| 3.5. HTTP/2 and HTTP/3 Responses | 3.5. HTTP/2 and HTTP/3 Responses | |||
| The UDP proxy SHALL indicate a successful response by replying with | The UDP proxy SHALL indicate a successful response by replying with | |||
| the following requirements: | the following requirements: | |||
| * the HTTP status code on the response SHALL be in the 2xx | * the HTTP status code on the response SHALL be in the 2xx | |||
| (Successful) range. | (Successful) range. | |||
| * the response SHALL meet the requirements of HTTP responses that | * the response SHALL meet the requirements of HTTP responses that | |||
| skipping to change at page 9, line 25 ¶ | skipping to change at line 406 ¶ | |||
| If any of these requirements are not met, the client MUST treat this | If any of these requirements are not met, the client MUST treat this | |||
| proxying attempt as failed and abort the request. | proxying attempt as failed and abort the request. | |||
| For example, the UDP proxy could respond with: | For example, the UDP proxy could respond with: | |||
| HEADERS | HEADERS | |||
| :status = 200 | :status = 200 | |||
| capsule-protocol = ?1 | capsule-protocol = ?1 | |||
| Figure 5: Example HTTP/2 Response | Figure 6: Example HTTP/2 Response | |||
| 3.6. Note About Draft Versions | ||||
| [[RFC editor: please remove this section before publication.]] | ||||
| In order to allow implementations to support multiple draft versions | ||||
| of this specification during its development, we introduce the | ||||
| "connect-udp-version" header field. When sent by the client, it | ||||
| contains a list of draft numbers supported by the client (e.g., | ||||
| "connect-udp-version: 0, 2"). When sent by the UDP proxy, it | ||||
| contains a single draft number selected by the UDP proxy from the | ||||
| list provided by the client (e.g., "connect-udp-version: 2"). | ||||
| Sending this header field is RECOMMENDED but not required. The | ||||
| "connect-udp-version" header field is a List Structured Field | ||||
| (https://www.rfc-editor.org/rfc/rfc8941#section-3.1). Each list | ||||
| member MUST be an Integer. | ||||
| 4. Context Identifiers | 4. Context Identifiers | |||
| The mechanism for proxying UDP in HTTP defined in this document | The mechanism for proxying UDP in HTTP defined in this document | |||
| allows future extensions to exchange HTTP Datagrams that carry | allows future extensions to exchange HTTP Datagrams that carry | |||
| different semantics from UDP payloads. Some of these extensions can | different semantics from UDP payloads. Some of these extensions can | |||
| augment UDP payloads with additional data, while others can exchange | augment UDP payloads with additional data, while others can exchange | |||
| data that is completely separate from UDP payloads. In order to | data that is completely separate from UDP payloads. In order to | |||
| accomplish this, all HTTP Datagrams associated with UDP Proxying | accomplish this, all HTTP Datagrams associated with UDP Proxying | |||
| request streams start with a context ID, see Section 5. | request streams start with a Context ID field; see Section 5. | |||
| Context IDs are 62-bit integers (0 to 2^62-1). Context IDs are | Context IDs are 62-bit integers (0 to 2^62-1). Context IDs are | |||
| encoded as variable-length integers, see Section 16 of [QUIC]. The | encoded as variable-length integers; see Section 16 of [QUIC]. The | |||
| context ID value of 0 is reserved for UDP payloads, while non-zero | Context ID value of 0 is reserved for UDP payloads, while non-zero | |||
| values are dynamically allocated: non-zero even-numbered context IDs | values are dynamically allocated. Non-zero even-numbered Context IDs | |||
| are client-allocated, and odd-numbered context IDs are proxy- | are client-allocated, and odd-numbered Context IDs are proxy- | |||
| allocated. The context ID namespace is tied to a given HTTP request: | 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 | it is possible for a Context ID with the same numeric value to be | |||
| simultaneously allocated in distinct requests, potentially with | simultaneously allocated in distinct requests, potentially with | |||
| different semantics. Context IDs MUST NOT be re-allocated within a | different semantics. Context IDs MUST NOT be re-allocated within a | |||
| given HTTP namespace but MAY be allocated in any order. The context | given HTTP namespace but MAY be allocated in any order. The Context | |||
| ID allocation restrictions to the use of even-numbered and odd- | ID allocation restrictions to the use of even-numbered and odd- | |||
| numbered context IDs exist in order to avoid the need for | numbered Context IDs exist in order to avoid the need for | |||
| synchronisation between endpoints. However, once a context ID has | synchronization between endpoints. However, once a Context ID has | |||
| been allocated, those restrictions do not apply to the use of the | been allocated, those restrictions do not apply to the use of the | |||
| context ID: it can be used by any client or UDP proxy, independent of | Context ID; it can be used by any client or UDP proxy, independent of | |||
| which endpoint initially allocated it. | which endpoint initially allocated it. | |||
| Registration is the action by which an endpoint informs its peer of | Registration is the action by which an endpoint informs its peer of | |||
| the semantics and format of a given context ID. This document does | the semantics and format of a given Context ID. This document does | |||
| not define how registration occurs. Future extensions MAY use HTTP | not define how registration occurs. Future extensions MAY use HTTP | |||
| header fields or capsules to register contexts. Depending on the | header fields or capsules to register Context IDs. Depending on the | |||
| method being used, it is possible for datagrams to be received with | method being used, it is possible for datagrams to be received with | |||
| Context IDs which have not yet been registered, for instance due to | Context IDs that have not yet been registered. For instance, this | |||
| reordering of the packet containing the datagram and the packet | can be due to reordering of the packet containing the datagram and | |||
| containing the registration message during transmission. | the packet containing the registration message during transmission. | |||
| 5. HTTP Datagram Payload Format | 5. HTTP Datagram Payload Format | |||
| When HTTP Datagrams (see Section 2 of [HTTP-DGRAM]) are associated | When HTTP Datagrams (see Section 2 of [HTTP-DGRAM]) are associated | |||
| with UDP proxying request streams, the HTTP Datagram Payload field | with UDP Proxying request streams, the HTTP Datagram Payload field | |||
| has the format defined in Figure 6. Note that when HTTP Datagrams | has the format defined in Figure 7, using notation from Section 1.3 | |||
| are encoded using QUIC DATAGRAM frames [DGRAM], the Context ID field | of [QUIC]. Note that when HTTP Datagrams are encoded using QUIC | |||
| defined below directly follows the Quarter Stream ID field which is | DATAGRAM frames [QUIC-DGRAM], the Context ID field defined below | |||
| at the start of the QUIC DATAGRAM frame payload (see Section 2.1 of | directly follows the Quarter Stream ID field, which is at the start | |||
| [HTTP-DGRAM]). | of the QUIC DATAGRAM frame payload; see Section 2.1 of [HTTP-DGRAM]. | |||
| UDP Proxying HTTP Datagram Payload { | UDP Proxying HTTP Datagram Payload { | |||
| Context ID (i), | Context ID (i), | |||
| Payload (..), | UDP Proxying Payload (..), | |||
| } | } | |||
| Figure 6: UDP Proxying HTTP Datagram Format | Figure 7: UDP Proxying HTTP Datagram Format | |||
| Context ID: A variable-length integer (see Section 16 of [QUIC]) | Context ID: A variable-length integer (see Section 16 of [QUIC]) | |||
| that contains the value of the Context ID. If an HTTP/3 Datagram | that contains the value of the Context ID. If an HTTP/3 Datagram | |||
| which carries an unknown Context ID is received, the receiver | that carries an unknown Context ID is received, the receiver SHALL | |||
| SHALL either drop that datagram silently or buffer it temporarily | either drop that datagram silently or buffer it temporarily (on | |||
| (on the order of a round trip) while awaiting the registration of | the order of a round trip) while awaiting the registration of the | |||
| the corresponding Context ID. | corresponding Context ID. | |||
| Payload: The payload of the datagram, whose semantics depend on | UDP Proxying Payload: The payload of the datagram, whose semantics | |||
| value of the previous field. Note that this field can be empty. | depend on the value of the previous field. Note that this field | |||
| can be empty. | ||||
| UDP packets are encoded using HTTP Datagrams with the Context ID set | UDP packets are encoded using HTTP Datagrams with the Context ID | |||
| to zero. When the Context ID is set to zero, the Payload field | field set to zero. When the Context ID field is set to zero, the UDP | |||
| contains the unmodified payload of a UDP packet (referred to as "data | Proxying Payload field contains the unmodified payload of a UDP | |||
| octets" in [UDP]). | packet (referred to as data octets in [UDP]). | |||
| By virtue of the definition of the UDP header [UDP], it is not | By virtue of the definition of the UDP header [UDP], it is not | |||
| possible to encode UDP payloads longer than 65527 bytes. Therefore, | possible to encode UDP payloads longer than 65527 bytes. Therefore, | |||
| endpoints MUST NOT send HTTP Datagrams with a Payload field longer | endpoints MUST NOT send HTTP Datagrams with a UDP Proxying Payload | |||
| than 65527 using Context ID zero. An endpoint that receives an HTTP | field longer than 65527 using Context ID zero. An endpoint that | |||
| Datagram using Context ID zero whose Payload field is longer than | receives an HTTP Datagram using Context ID zero whose UDP Proxying | |||
| 65527 MUST abort the corresponding stream. If a UDP proxy knows it | Payload field is longer than 65527 MUST abort the corresponding | |||
| can only send out UDP packets of a certain length due to its | stream. If a UDP proxy knows it can only send out UDP packets of a | |||
| underlying link MTU, it has no choice but to discard incoming HTTP | certain length due to its underlying link MTU, it has no choice but | |||
| Datagrams using Context ID zero whose Payload field is longer than | to discard incoming HTTP Datagrams using Context ID zero whose UDP | |||
| that limit. If the discarded HTTP Datagram was transported by a | Proxying Payload field is longer than that limit. If the discarded | |||
| DATAGRAM capsule, the receiver SHOULD discard that capsule without | HTTP Datagram was transported by a DATAGRAM capsule, the receiver | |||
| buffering the capsule contents. | SHOULD discard that capsule without buffering the capsule contents. | |||
| If a UDP proxy receives an HTTP Datagram before it has received the | If a UDP proxy receives an HTTP Datagram before it has received the | |||
| corresponding request, it SHALL either drop that HTTP Datagram | corresponding request, it SHALL either drop that HTTP Datagram | |||
| silently or buffer it temporarily (on the order of a round trip) | silently or buffer it temporarily (on the order of a round trip) | |||
| while awaiting the corresponding request. | while awaiting the corresponding request. | |||
| Note that buffering datagrams (either because the request was not yet | Note that buffering datagrams (either because the request was not yet | |||
| received, or because the Context ID is not yet known) consumes | received or because the Context ID is not yet known) consumes | |||
| resources. Receivers that buffer datagrams SHOULD apply buffering | resources. Receivers that buffer datagrams SHOULD apply buffering | |||
| limits in order to reduce the risk of resource exhaustion occuring. | limits in order to reduce the risk of resource exhaustion occurring. | |||
| For example, receivers can limit the total number of buffered | For example, receivers can limit the total number of buffered | |||
| datagrams, or the cumulative size of buffered datagrams, on a per- | datagrams or the cumulative size of buffered datagrams on a per- | |||
| stream, per-context, or per-connection basis. | stream, per-context, or per-connection basis. | |||
| A client MAY optimistically start sending UDP packets in HTTP | A client MAY optimistically start sending UDP packets in HTTP | |||
| Datagrams before receiving the response to its UDP proxying request. | Datagrams before receiving the response to its UDP proxying request. | |||
| However, implementers should note that such proxied packets may not | However, implementers should note that such proxied packets may not | |||
| be processed by the UDP proxy if it responds to the request with a | be processed by the UDP proxy if it responds to the request with a | |||
| failure, or if the proxied packets are received by the UDP proxy | failure or if the proxied packets are received by the UDP proxy | |||
| before the request and the UDP proxy chooses to not buffer them. | before the request and the UDP proxy chooses to not buffer them. | |||
| 6. Performance Considerations | 6. Performance Considerations | |||
| Bursty traffic can often lead to temporally correlated packet losses, | Bursty traffic can often lead to temporally correlated packet losses; | |||
| which in turn can lead to suboptimal responses from congestion | in turn, this can lead to suboptimal responses from congestion | |||
| controllers in protocols running over UDP. To avoid this, UDP | controllers in protocols running over UDP. To avoid this, UDP | |||
| proxies SHOULD strive to avoid increasing burstiness of UDP traffic: | proxies SHOULD strive to avoid increasing burstiness of UDP traffic; | |||
| they SHOULD NOT queue packets in order to increase batching. | they SHOULD NOT queue packets in order to increase batching. | |||
| When the protocol running over UDP that is being proxied uses | When the protocol running over UDP that is being proxied uses | |||
| congestion control (e.g., [QUIC]), the proxied traffic will incur at | congestion control (e.g., [QUIC]), the proxied traffic will incur at | |||
| least two nested congestion controllers. The underlying HTTP | least two nested congestion controllers. The underlying HTTP | |||
| connection MUST NOT disable congestion control unless it has an out- | connection MUST NOT disable congestion control unless it has an out- | |||
| of-band way of knowing with absolute certainty that the inner traffic | of-band way of knowing with absolute certainty that the inner traffic | |||
| is congestion-controlled. | is congestion-controlled. | |||
| If a client or UDP proxy with a connection containing a UDP proxying | If a client or UDP proxy with a connection containing a UDP Proxying | |||
| request stream disables congestion control, it MUST NOT signal | request stream disables congestion control, it MUST NOT signal | |||
| Explicit Congestion Notification (ECN) [ECN] support on that | Explicit Congestion Notification (ECN) [ECN] support on that | |||
| connection. That is, it MUST mark all IP headers with the Not-ECT | 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 | 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 | frames or the TCP ECE bit, as the peer may not have disabled | |||
| congestion control. | congestion control. | |||
| When the protocol running over UDP that is being proxied uses loss | When the protocol running over UDP that is being proxied uses loss | |||
| recovery (e.g., [QUIC]), and the underlying HTTP connection runs over | recovery (e.g., [QUIC]), and the underlying HTTP connection runs over | |||
| TCP, the proxied traffic will incur at least two nested loss recovery | TCP, the proxied traffic will incur at least two nested loss recovery | |||
| mechanisms. This can reduce performance as both can sometimes | mechanisms. This can reduce performance as both can sometimes | |||
| independently retransmit the same data. To avoid this, UDP proxying | independently retransmit the same data. To avoid this, UDP proxying | |||
| SHOULD be performed over HTTP/3 to allow leveraging the QUIC DATAGRAM | SHOULD be performed over HTTP/3 to allow leveraging the QUIC DATAGRAM | |||
| frame. | frame. | |||
| 6.1. MTU Considerations | 6.1. MTU Considerations | |||
| When using HTTP/3 with the QUIC Datagram extension [DGRAM], UDP | When using HTTP/3 with the QUIC Datagram extension [QUIC-DGRAM], UDP | |||
| payloads are transmitted in QUIC DATAGRAM frames. Since those cannot | payloads are transmitted in QUIC DATAGRAM frames. Since those cannot | |||
| be fragmented, they can only carry payloads up to a given length | be fragmented, they can only carry payloads up to a given length | |||
| determined by the QUIC connection configuration and the path MTU. If | determined by the QUIC connection configuration and the Path MTU | |||
| a UDP proxy is using QUIC DATAGRAM frames and it receives a UDP | (PMTU). If a UDP proxy is using QUIC DATAGRAM frames and it receives | |||
| payload from the target that will not fit inside a QUIC DATAGRAM | a UDP payload from the target that will not fit inside a QUIC | |||
| frame, the UDP proxy SHOULD NOT send the UDP payload in a DATAGRAM | DATAGRAM frame, the UDP proxy SHOULD NOT send the UDP payload in a | |||
| capsule, as that defeats the end-to-end unreliability characteristic | DATAGRAM capsule, as that defeats the end-to-end unreliability | |||
| that methods such as Datagram Packetization Layer Path MTU Discovery | characteristic that methods such as Datagram Packetization Layer PMTU | |||
| (DPLPMTUD) depend on [DPLPMTUD]. In this scenario, the UDP proxy | Discovery (DPLPMTUD) depend on [DPLPMTUD]. In this scenario, the UDP | |||
| SHOULD drop the UDP payload and send an ICMP "Packet Too Big" message | proxy SHOULD drop the UDP payload and send an ICMP Packet Too Big | |||
| to the target, see Section 3.2 of [ICMP6]. | message to the target; see Section 3.2 of [ICMP6]. | |||
| 6.2. Tunneling of ECN Marks | 6.2. Tunneling of ECN Marks | |||
| UDP proxying does not create an IP-in-IP tunnel, so the guidance in | UDP proxying does not create an IP-in-IP tunnel, so the guidance in | |||
| [ECN-TUNNEL] about transferring ECN marks between inner and outer IP | [ECN-TUNNEL] about transferring ECN marks between inner and outer IP | |||
| headers does not apply. There is no inner IP header in UDP proxying | headers does not apply. There is no inner IP header in UDP proxying | |||
| tunnels. | tunnels. | |||
| Note that UDP proxying clients do not have the ability in this | In this specification, note that UDP proxying clients do not have the | |||
| specification to control the ECN codepoints on UDP packets the UDP | ability to control the ECN codepoints on UDP packets the UDP proxy | |||
| proxy sends to the target, nor can UDP proxies communicate the | sends to the target, nor can UDP proxies communicate the markings of | |||
| markings of each UDP packet from target to UDP proxy. | each UDP packet from target to UDP proxy. | |||
| A UDP proxy MUST ignore ECN bits in the IP header of UDP packets | A UDP proxy MUST ignore ECN bits in the IP header of UDP packets | |||
| received from the target, and MUST set the ECN bits to Not-ECT on UDP | received from the target, and it MUST set the ECN bits to Not-ECT on | |||
| packets it sends to the target. These do not relate to the ECN | UDP packets it sends to the target. These do not relate to the ECN | |||
| markings of packets sent between client and UDP proxy in any way. | markings of packets sent between client and UDP proxy in any way. | |||
| 7. Security Considerations | 7. Security Considerations | |||
| There are significant risks in allowing arbitrary clients to | There are significant risks in allowing arbitrary clients to | |||
| establish a tunnel to arbitrary targets, as that could allow bad | establish a tunnel to arbitrary targets, as that could allow bad | |||
| actors to send traffic and have it attributed to the UDP proxy. HTTP | actors to send traffic and have it attributed to the UDP proxy. HTTP | |||
| servers that support UDP proxying ought to restrict its use to | servers that support UDP proxying ought to restrict its use to | |||
| authenticated users. | authenticated users. | |||
| There exist software and network deployments that perform access | There exist software and network deployments that perform access | |||
| control checks based on the source IP address of incoming requests. | control checks based on the source IP address of incoming requests. | |||
| For example, some software allows unauthenticated configuration | For example, some software allows unauthenticated configuration | |||
| changes if they originated from 127.0.0.1. Such software could be | changes if they originated from 127.0.0.1. Such software could be | |||
| running on the same host as the UDP proxy, or in the same broadcast | running on the same host as the UDP proxy or in the same broadcast | |||
| domain. Proxied UDP traffic would then be received with a source IP | domain. Proxied UDP traffic would then be received with a source IP | |||
| address belonging to the UDP proxy. If this source address is used | address belonging to the UDP proxy. If this source address is used | |||
| for access control, UDP proxying clients could use the UDP proxy to | for access control, UDP proxying clients could use the UDP proxy to | |||
| escalate their access privileges beyond those they might otherwise | escalate their access privileges beyond those they might otherwise | |||
| have. This could lead to unauthorized access by UDP proxying clients | have. This could lead to unauthorized access by UDP proxying clients | |||
| unless the UDP proxy disallows UDP proxying requests to vulnerable | unless the UDP proxy disallows UDP proxying requests to vulnerable | |||
| targets, such as the UDP proxy's own addresses and localhost, link- | targets, such as the UDP proxy's own addresses and localhost, link- | |||
| local, multicast, and broadcast addresses. UDP proxies can use the | local, multicast, and broadcast addresses. UDP proxies can use the | |||
| destination_ip_prohibited Proxy Error Type from Section 2.3.5 of | destination_ip_prohibited Proxy Error Type from Section 2.3.5 of | |||
| [PROXY-STATUS] when rejecting such requests. | [PROXY-STATUS] when rejecting such requests. | |||
| UDP proxies share many similarities to TCP CONNECT proxies when | UDP proxies share many similarities with TCP CONNECT proxies when | |||
| considering them as infrastructure for abuse to enable denial of | considering them as infrastructure for abuse to enable denial-of- | |||
| service attacks. Both can obfuscate the attacker's source address | service (DoS) attacks. Both can obfuscate the attacker's source | |||
| from the attack target. In the case of a stateless volumetric attack | address from the attack target. In the case of a stateless | |||
| (e.g., a TCP SYN flood or a UDP flood), both types of proxies pass | volumetric attack (e.g., a TCP SYN flood or a UDP flood), both types | |||
| the traffic to the target host. With stateful volumetric attacks | of proxies pass the traffic to the target host. With stateful | |||
| (e.g., HTTP flooding) being sent over a TCP CONNECT proxy, the proxy | volumetric attacks (e.g., HTTP flooding) being sent over a TCP | |||
| will only send data if the target has indicated its willingness to | CONNECT proxy, the proxy will only send data if the target has | |||
| accept data by responding with a TCP SYN-ACK. Once the path to the | indicated its willingness to accept data by responding with a TCP | |||
| target is flooded, the TCP CONNECT proxy will no longer receive | SYN-ACK. Once the path to the target is flooded, the TCP CONNECT | |||
| replies from the target and will stop sending data. Since UDP does | proxy will no longer receive replies from the target and will stop | |||
| not establish shared state between the UDP proxy and the target, the | sending data. Since UDP does not establish shared state between the | |||
| UDP proxy could continue sending data to the target in such a | UDP proxy and the target, the UDP proxy could continue sending data | |||
| situation. While a UDP proxy could potentially limit the number of | to the target in such a situation. While a UDP proxy could | |||
| UDP packets it is willing to forward until it has observed a response | potentially limit the number of UDP packets it is willing to forward | |||
| from the target, that provides limited protection against denial of | until it has observed a response from the target, that provides | |||
| service attacks when attacks target open UDP ports where the protocol | limited protection against DoS attacks when attacks target open UDP | |||
| running over UDP would respond, and that would be interpreted as | ports where the protocol running over UDP would respond and that | |||
| willingness to accept UDP by the UDP proxy. Such a packet limit | would be interpreted as willingness to accept UDP by the UDP proxy. | |||
| could also cause issues for valid traffic. | Such a packet limit could also cause issues for valid traffic. | |||
| The security considerations described in Section 4 of [HTTP-DGRAM] | The security considerations described in Section 4 of [HTTP-DGRAM] | |||
| also apply here. Since it is possible to tunnel IP packets over UDP, | also apply here. Since it is possible to tunnel IP packets over UDP, | |||
| the guidance in [TUNNEL-SECURITY] can apply. | the guidance in [TUNNEL-SECURITY] can apply. | |||
| 8. IANA Considerations | 8. IANA Considerations | |||
| 8.1. HTTP Upgrade Token | 8.1. HTTP Upgrade Token | |||
| This document will request IANA to register "connect-udp" in the | IANA has registered "connect-udp" in the "HTTP Upgrade Tokens" | |||
| "HTTP Upgrade Tokens" registry maintained at | registry maintained at <https://www.iana.org/assignments/http- | |||
| <https://www.iana.org/assignments/http-upgrade-tokens>. | upgrade-tokens>. | |||
| Value: connect-udp | Value: connect-udp | |||
| Description: Proxying of UDP Payloads | Description: Proxying of UDP Payloads | |||
| Expected Version Tokens: None | Expected Version Tokens: None | |||
| Reference: This document | Reference: RFC 9298 | |||
| 8.2. Well-Known URI | 8.2. Well-Known URI | |||
| This document will request IANA to register "masque" in the "Well- | IANA has registered "masque" in the "Well-Known URIs" registry | |||
| Known URIs" registry maintained at <https://www.iana.org/assignments/ | maintained at <https://www.iana.org/assignments/well-known-uris>. | |||
| well-known-uris>. | ||||
| URI Suffix: masque | URI Suffix: masque | |||
| Change Controller: IETF | Change Controller: IETF | |||
| Reference: This document | Reference: RFC 9298 | |||
| Status: permanent (if this document is approved) | Status: permanent | |||
| Related Information: Includes all resources identified with the path | Related Information: Includes all resources identified with the path | |||
| prefix "/.well-known/masque/udp/" | prefix "/.well-known/masque/udp/" | |||
| 9. References | 9. References | |||
| 9.1. Normative References | 9.1. Normative References | |||
| [DGRAM] Pauly, T., Kinnear, E., and D. Schinazi, "An Unreliable | [ABNF] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax | |||
| Datagram Extension to QUIC", RFC 9221, | Specifications: ABNF", RFC 2234, DOI 10.17487/RFC2234, | |||
| DOI 10.17487/RFC9221, March 2022, | November 1997, <https://www.rfc-editor.org/info/rfc2234>. | |||
| <https://www.rfc-editor.org/rfc/rfc9221>. | ||||
| [ECN] Ramakrishnan, K., Floyd, S., and D. Black, "The Addition | [ECN] Ramakrishnan, K., Floyd, S., and D. Black, "The Addition | |||
| of Explicit Congestion Notification (ECN) to IP", | of Explicit Congestion Notification (ECN) to IP", | |||
| RFC 3168, DOI 10.17487/RFC3168, September 2001, | RFC 3168, DOI 10.17487/RFC3168, September 2001, | |||
| <https://www.rfc-editor.org/rfc/rfc3168>. | <https://www.rfc-editor.org/info/rfc3168>. | |||
| [EXT-CONNECT2] | [EXT-CONNECT2] | |||
| McManus, P., "Bootstrapping WebSockets with HTTP/2", | McManus, P., "Bootstrapping WebSockets with HTTP/2", | |||
| RFC 8441, DOI 10.17487/RFC8441, September 2018, | RFC 8441, DOI 10.17487/RFC8441, September 2018, | |||
| <https://www.rfc-editor.org/rfc/rfc8441>. | <https://www.rfc-editor.org/info/rfc8441>. | |||
| [EXT-CONNECT3] | [EXT-CONNECT3] | |||
| Hamilton, R., "Bootstrapping WebSockets with HTTP/3", | Hamilton, R., "Bootstrapping WebSockets with HTTP/3", | |||
| RFC 9220, DOI 10.17487/RFC9220, June 2022, | RFC 9220, DOI 10.17487/RFC9220, June 2022, | |||
| <https://www.rfc-editor.org/rfc/rfc9220>. | <https://www.rfc-editor.org/info/rfc9220>. | |||
| [HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, | [HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, | |||
| Ed., "HTTP Semantics", STD 97, RFC 9110, | Ed., "HTTP Semantics", STD 97, RFC 9110, | |||
| DOI 10.17487/RFC9110, June 2022, | DOI 10.17487/RFC9110, June 2022, | |||
| <https://www.rfc-editor.org/rfc/rfc9110>. | <https://www.rfc-editor.org/info/rfc9110>. | |||
| [HTTP-DGRAM] | [HTTP-DGRAM] | |||
| Schinazi, D. and L. Pardue, "HTTP Datagrams and the | Schinazi, D. and L. Pardue, "HTTP Datagrams and the | |||
| Capsule Protocol", Work in Progress, Internet-Draft, | Capsule Protocol", RFC 9297, DOI 10.17487/RFC9297, August | |||
| draft-ietf-masque-h3-datagram-11, 17 June 2022, | 2022, <https://www.rfc-editor.org/info/rfc9297>. | |||
| <https://datatracker.ietf.org/doc/html/draft-ietf-masque- | ||||
| h3-datagram-11>. | ||||
| [HTTP/1.1] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, | [HTTP/1.1] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, | |||
| Ed., "HTTP/1.1", STD 99, RFC 9112, DOI 10.17487/RFC9112, | Ed., "HTTP/1.1", STD 99, RFC 9112, DOI 10.17487/RFC9112, | |||
| June 2022, <https://www.rfc-editor.org/rfc/rfc9112>. | June 2022, <https://www.rfc-editor.org/info/rfc9112>. | |||
| [HTTP/2] Thomson, M., Ed. and C. Benfield, Ed., "HTTP/2", RFC 9113, | [HTTP/2] Thomson, M., Ed. and C. Benfield, Ed., "HTTP/2", RFC 9113, | |||
| DOI 10.17487/RFC9113, June 2022, | DOI 10.17487/RFC9113, June 2022, | |||
| <https://www.rfc-editor.org/rfc/rfc9113>. | <https://www.rfc-editor.org/info/rfc9113>. | |||
| [HTTP/3] Bishop, M., Ed., "HTTP/3", RFC 9114, DOI 10.17487/RFC9114, | [HTTP/3] Bishop, M., Ed., "HTTP/3", RFC 9114, DOI 10.17487/RFC9114, | |||
| June 2022, <https://www.rfc-editor.org/rfc/rfc9114>. | June 2022, <https://www.rfc-editor.org/info/rfc9114>. | |||
| [PROXY-STATUS] | [PROXY-STATUS] | |||
| Nottingham, M. and P. Sikora, "The Proxy-Status HTTP | Nottingham, M. and P. Sikora, "The Proxy-Status HTTP | |||
| Response Header Field", RFC 9209, DOI 10.17487/RFC9209, | Response Header Field", RFC 9209, DOI 10.17487/RFC9209, | |||
| June 2022, <https://www.rfc-editor.org/rfc/rfc9209>. | June 2022, <https://www.rfc-editor.org/info/rfc9209>. | |||
| [QUIC] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based | [QUIC] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based | |||
| Multiplexed and Secure Transport", RFC 9000, | Multiplexed and Secure Transport", RFC 9000, | |||
| DOI 10.17487/RFC9000, May 2021, | DOI 10.17487/RFC9000, May 2021, | |||
| <https://www.rfc-editor.org/rfc/rfc9000>. | <https://www.rfc-editor.org/info/rfc9000>. | |||
| [QUIC-DGRAM] | ||||
| Pauly, T., Kinnear, E., and D. Schinazi, "An Unreliable | ||||
| Datagram Extension to QUIC", RFC 9221, | ||||
| DOI 10.17487/RFC9221, March 2022, | ||||
| <https://www.rfc-editor.org/info/rfc9221>. | ||||
| [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | |||
| Requirement Levels", BCP 14, RFC 2119, | Requirement Levels", BCP 14, RFC 2119, | |||
| DOI 10.17487/RFC2119, March 1997, | DOI 10.17487/RFC2119, March 1997, | |||
| <https://www.rfc-editor.org/rfc/rfc2119>. | <https://www.rfc-editor.org/info/rfc2119>. | |||
| [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | |||
| 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | |||
| May 2017, <https://www.rfc-editor.org/rfc/rfc8174>. | May 2017, <https://www.rfc-editor.org/info/rfc8174>. | |||
| [TCP] Postel, J., "Transmission Control Protocol", STD 7, | [TCP] Postel, J., "Transmission Control Protocol", STD 7, | |||
| RFC 793, DOI 10.17487/RFC0793, September 1981, | RFC 793, DOI 10.17487/RFC0793, September 1981, | |||
| <https://www.rfc-editor.org/rfc/rfc793>. | <https://www.rfc-editor.org/info/rfc793>. | |||
| [TEMPLATE] Gregorio, J., Fielding, R., Hadley, M., Nottingham, M., | [TEMPLATE] Gregorio, J., Fielding, R., Hadley, M., Nottingham, M., | |||
| and D. Orchard, "URI Template", RFC 6570, | and D. Orchard, "URI Template", RFC 6570, | |||
| DOI 10.17487/RFC6570, March 2012, | DOI 10.17487/RFC6570, March 2012, | |||
| <https://www.rfc-editor.org/rfc/rfc6570>. | <https://www.rfc-editor.org/info/rfc6570>. | |||
| [UDP] Postel, J., "User Datagram Protocol", STD 6, RFC 768, | [UDP] Postel, J., "User Datagram Protocol", STD 6, RFC 768, | |||
| DOI 10.17487/RFC0768, August 1980, | DOI 10.17487/RFC0768, August 1980, | |||
| <https://www.rfc-editor.org/rfc/rfc768>. | <https://www.rfc-editor.org/info/rfc768>. | |||
| [URI] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform | ||||
| Resource Identifier (URI): Generic Syntax", STD 66, | ||||
| RFC 3986, DOI 10.17487/RFC3986, January 2005, | ||||
| <https://www.rfc-editor.org/info/rfc3986>. | ||||
| 9.2. Informative References | 9.2. Informative References | |||
| [BEHAVE] Audet, F., Ed. and C. Jennings, "Network Address | [BEHAVE] Audet, F., Ed. and C. Jennings, "Network Address | |||
| Translation (NAT) Behavioral Requirements for Unicast | Translation (NAT) Behavioral Requirements for Unicast | |||
| UDP", BCP 127, RFC 4787, DOI 10.17487/RFC4787, January | UDP", BCP 127, RFC 4787, DOI 10.17487/RFC4787, January | |||
| 2007, <https://www.rfc-editor.org/rfc/rfc4787>. | 2007, <https://www.rfc-editor.org/info/rfc4787>. | |||
| [DPLPMTUD] Fairhurst, G., Jones, T., Tüxen, M., Rüngeler, I., and T. | [DPLPMTUD] Fairhurst, G., Jones, T., Tüxen, M., Rüngeler, I., and T. | |||
| Völker, "Packetization Layer Path MTU Discovery for | Völker, "Packetization Layer Path MTU Discovery for | |||
| Datagram Transports", RFC 8899, DOI 10.17487/RFC8899, | Datagram Transports", RFC 8899, DOI 10.17487/RFC8899, | |||
| September 2020, <https://www.rfc-editor.org/rfc/rfc8899>. | September 2020, <https://www.rfc-editor.org/info/rfc8899>. | |||
| [ECN-TUNNEL] | [ECN-TUNNEL] | |||
| Briscoe, B., "Tunnelling of Explicit Congestion | Briscoe, B., "Tunnelling of Explicit Congestion | |||
| Notification", RFC 6040, DOI 10.17487/RFC6040, November | Notification", RFC 6040, DOI 10.17487/RFC6040, November | |||
| 2010, <https://www.rfc-editor.org/rfc/rfc6040>. | 2010, <https://www.rfc-editor.org/info/rfc6040>. | |||
| [HELIUM] Schwartz, B. M., "Hybrid Encapsulation Layer for IP and | ||||
| UDP Messages (HELIUM)", Work in Progress, Internet-Draft, | ||||
| draft-schwartz-httpbis-helium-00, 25 June 2018, | ||||
| <https://datatracker.ietf.org/doc/html/draft-schwartz- | ||||
| httpbis-helium-00>. | ||||
| [HiNT] Pardue, L., "HTTP-initiated Network Tunnelling (HiNT)", | ||||
| Work in Progress, Internet-Draft, draft-pardue-httpbis- | ||||
| http-network-tunnelling-00, 2 July 2018, | ||||
| <https://datatracker.ietf.org/doc/html/draft-pardue- | ||||
| httpbis-http-network-tunnelling-00>. | ||||
| [ICMP6] Conta, A., Deering, S., and M. Gupta, Ed., "Internet | [ICMP6] Conta, A., Deering, S., and M. Gupta, Ed., "Internet | |||
| Control Message Protocol (ICMPv6) for the Internet | Control Message Protocol (ICMPv6) for the Internet | |||
| Protocol Version 6 (IPv6) Specification", STD 89, | Protocol Version 6 (IPv6) Specification", STD 89, | |||
| RFC 4443, DOI 10.17487/RFC4443, March 2006, | RFC 4443, DOI 10.17487/RFC4443, March 2006, | |||
| <https://www.rfc-editor.org/rfc/rfc4443>. | <https://www.rfc-editor.org/info/rfc4443>. | |||
| [MASQUE-ORIGINAL] | ||||
| Schinazi, D., "The MASQUE Protocol", Work in Progress, | ||||
| Internet-Draft, draft-schinazi-masque-00, 28 February | ||||
| 2019, <https://datatracker.ietf.org/doc/html/draft- | ||||
| schinazi-masque-00>. | ||||
| [TUNNEL-SECURITY] | [TUNNEL-SECURITY] | |||
| Krishnan, S., Thaler, D., and J. Hoagland, "Security | Krishnan, S., Thaler, D., and J. Hoagland, "Security | |||
| Concerns with IP Tunneling", RFC 6169, | Concerns with IP Tunneling", RFC 6169, | |||
| DOI 10.17487/RFC6169, April 2011, | DOI 10.17487/RFC6169, April 2011, | |||
| <https://www.rfc-editor.org/rfc/rfc6169>. | <https://www.rfc-editor.org/info/rfc6169>. | |||
| [UDP-USAGE] | [UDP-USAGE] | |||
| Eggert, L., Fairhurst, G., and G. Shepherd, "UDP Usage | Eggert, L., Fairhurst, G., and G. Shepherd, "UDP Usage | |||
| Guidelines", BCP 145, RFC 8085, DOI 10.17487/RFC8085, | Guidelines", BCP 145, RFC 8085, DOI 10.17487/RFC8085, | |||
| March 2017, <https://www.rfc-editor.org/rfc/rfc8085>. | March 2017, <https://www.rfc-editor.org/info/rfc8085>. | |||
| [URI] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform | ||||
| Resource Identifier (URI): Generic Syntax", STD 66, | ||||
| RFC 3986, DOI 10.17487/RFC3986, January 2005, | ||||
| <https://www.rfc-editor.org/rfc/rfc3986>. | ||||
| [WEBSOCKET] | [WEBSOCKET] | |||
| Fette, I. and A. Melnikov, "The WebSocket Protocol", | Fette, I. and A. Melnikov, "The WebSocket Protocol", | |||
| RFC 6455, DOI 10.17487/RFC6455, December 2011, | RFC 6455, DOI 10.17487/RFC6455, December 2011, | |||
| <https://www.rfc-editor.org/rfc/rfc6455>. | <https://www.rfc-editor.org/info/rfc6455>. | |||
| Acknowledgments | Acknowledgments | |||
| This document is a product of the MASQUE Working Group, and the | This document is a product of the MASQUE Working Group, and the | |||
| author thanks all MASQUE enthusiasts for their contibutions. This | author thanks all MASQUE enthusiasts for their contributions. This | |||
| proposal was inspired directly or indirectly by prior work from many | proposal was inspired directly or indirectly by prior work from many | |||
| people, in particular HELIUM (https://www.ietf.org/archive/id/draft- | people, in particular [HELIUM] by Ben Schwartz, [HiNT] by Lucas | |||
| schwartz-httpbis-helium-00.txt) by Ben Schwartz, HiNT | Pardue, and the original MASQUE Protocol [MASQUE-ORIGINAL] by the | |||
| (https://www.ietf.org/archive/id/draft-pardue-httpbis-http-network- | ||||
| tunnelling-00.txt) by Lucas Pardue, and the original MASQUE Protocol | ||||
| (https://www.ietf.org/archive/id/draft-schinazi-masque-00.txt) by the | ||||
| author of this document. | author of this document. | |||
| The author would like to thank Eric Rescorla for suggesting the use | The author would like to thank Eric Rescorla for suggesting the use | |||
| of an HTTP method to proxy UDP. The author is indebted to Mark | of an HTTP method to proxy UDP. The author is indebted to Mark | |||
| Nottingham and Lucas Pardue for the many improvements they | Nottingham and Lucas Pardue for the many improvements they | |||
| contributed to this document. The extensibility design in this | contributed to this document. The extensibility design in this | |||
| document came out of the HTTP Datagrams Design Team, whose members | document came out of the HTTP Datagrams Design Team, whose members | |||
| were Alan Frindell, Alex Chernyakhovsky, Ben Schwartz, Eric Rescorla, | were Alan Frindell, Alex Chernyakhovsky, Ben Schwartz, Eric Rescorla, | |||
| Lucas Pardue, Marcus Ihlar, Martin Thomson, Mike Bishop, Tommy Pauly, | Lucas Pardue, Marcus Ihlar, Martin Thomson, Mike Bishop, Tommy Pauly, | |||
| Victor Vasiliev, and the author of this document. | Victor Vasiliev, and the author of this document. | |||
| End of changes. 107 change blocks. | ||||
| 294 lines changed or deleted | 298 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. | ||||