Proxying IP in HTTP
updates
- rfc-9298 — Proxying UDP in HTTP
Extracted elements (30)
Context IDs are split into even (client-allocated) and odd (proxy-allocated) values to avoid requiring synchronization between endpoints when allocating new Context IDs for protocol extensions. Once allocated, a Context ID may be used by either endpoint regardless of who allocated it.
The Hop Count (TTL) is decremented upon encapsulation rather than decapsulation, matching the behavior of IPsec. This prevents infinite forwarding loops when routing loops exist in the network. The decrement does not apply to IP packets generated by the IP proxying endpoint itself.
ICMP traffic is always allowed through an IP proxying tunnel regardless of the 'ipproto' URI Template variable value or the IP Protocol field in ROUTE_ADVERTISEMENT entries. This ensures ICMP error signalling (e.g., Packet Too Big, Destination Unreachable) always functions.
In ROUTE_ADVERTISEMENT capsules, endpoints MUST NOT send routes that overlap via the IP Protocol = 0 (all protocols) ambiguity. If a receiver detects such overlap, it MUST abort the IP proxying request stream (validating this is OPTIONAL, but the abort upon detection is required).
IP proxies MUST validate whether the decoded 'target' and 'ipproto' URI Template variables meet format requirements. If 'target' is a DNS name, the IP proxy MUST perform DNS resolution before replying. On DNS errors, the proxy MUST reject the request and SHOULD send a Proxy-Status header field with the dns_error proxy error type.
IP proxying endpoints that operate as routers and support IPv6 MUST ensure that the IP tunnel link MTU is at least 1280 bytes. If using QUIC DATAGRAM frames and the QUIC MTU is too low to allow sending 1280 bytes, the endpoint MUST abort the IP proxying request stream.
IP proxying over HTTP MUST be operated over TLS or QUIC encryption, or another equivalent encryption protocol, to provide confidentiality, integrity, and authentication.
The URI Template used to configure clients MUST be a level 3 template or lower, MUST be in absolute form with non-empty scheme, authority, and path components, and MUST NOT contain non-ASCII Unicode characters or use Reserved/Fragment/Label/Path-Segment expansion operators. If a client detects any requirement violation, it MUST reject its configuration and abort the request.
When implementing scoping or routing by Internet Protocol Number, implementations MUST walk the chain of IPv6 extension headers to find the outermost non-extension Internet Protocol Number when matching against scoping rules. IP proxies MAY reject requests scoped to extension header protocol numbers.
When IP packet forwarding fails (e.g., no route, policy rejection, MTU exceeded), IP proxying endpoints SHOULD use ICMP/ICMPv6 to signal the forwarding error to the peer by generating ICMP packets and sending them via HTTP Datagrams. Relevant errors include Destination Unreachable and Packet Too Big.
When IP proxying endpoints forward IP packets between different links, they will decrement the IP Hop Count (or TTL) upon encapsulation but NOT upon decapsulation. This prevents infinite loops in the presence of routing loops.
When tunneled packets subject to outer congestion control carry different DSCP markings, the IP proxying endpoint MUST NOT copy the DSCP field from the inner IP header to the outer IP header, to prevent reordering from degrading the congestion controller. If using QUIC datagrams outside congestion control, endpoints MAY translate DSCP but MUST NOT coalesce inner packets with different DSCP markings into the same outer packet.
When using HTTP/1.1, an IP proxying request SHALL use GET method, include Connection: Upgrade, and include Upgrade: connect-ip. A successful response SHALL use status code 101 (Switching Protocols) with matching Connection and Upgrade headers. If requirements are not met, the client MUST treat the proxying attempt as failed and close the connection.
When using HTTP/2 or HTTP/3, IP proxying requests use HTTP Extended CONNECT with :method = CONNECT, :protocol = connect-ip, and non-empty :path and :scheme pseudo-header fields. A successful response SHALL have a 2xx status code; any other code causes the client to MUST abort the request.
Address assignment can function as a tracking vector: if a proxy partitions its address space by client and assigns distinct ranges per client, target hosts can correlate IP packets to the same client. Proxies SHOULD avoid persistent per-client address (prefix) assignment when possible. Transferring DSCP markings to outer headers in privacy-sensitive contexts is NOT RECOMMENDED as it exposes end-to-end flow information to on-path observers.
Context IDs are 62-bit integers encoded as QUIC variable-length integers. Context ID 0 is reserved for IP payloads. Even non-zero Context IDs are client-allocated; odd non-zero Context IDs are proxy-allocated. Context IDs MUST NOT be re-allocated within a given HTTP request. The even/odd split avoids synchronization between endpoints.
The ADDRESS_ASSIGN capsule (type 0x01) allows an endpoint to assign its peer a list of IP addresses or prefixes. Every capsule contains the full list currently assigned; if a previously assigned address is absent, it is considered removed. Each Assigned Address entry contains Request ID (variable-length integer), IP Version (8-bit, 4 or 6), IP Address (32 or 128 bits), and IP Prefix Length (8-bit).
The ADDRESS_REQUEST capsule (type 0x02) allows an endpoint to request IP address assignment from its peer, optionally indicating a preferred address. Request IDs MUST NOT be reused and MUST NOT be zero. If the capsule contains zero Requested Addresses, the receiver MUST abort the IP proxying request stream.
The 'connect-ip' HTTP upgrade token is defined to negotiate an IP tunnel over HTTP. Clients issue requests containing this token, and the resulting tunnels use the Capsule Protocol with HTTP Datagrams carrying IP packets. The tunnel lifetime is tied to the HTTP request stream.
The ROUTE_ADVERTISEMENT capsule (type 0x03) communicates to a peer which IP address ranges the sender is willing to route. Each capsule supersedes prior ones. Ranges MUST be ordered: IP Version ascending, then IP Protocol ascending, then non-overlapping End/Start addresses. A malformed or non-compliant capsule MUST cause the receiver to abort the IP proxying request stream.
IANA created the 'MASQUE URI Suffixes' registry (Expert Review policy) governing path segments following '/.well-known/masque/'. Initial entries: 'udp' (UDP Proxying, RFC 9298) and 'ip' (IP Proxying, RFC 9484).
IANA registered 'connect-ip' in the 'HTTP Upgrade Tokens' registry. Value: connect-ip; Description: Proxying of IP Payloads; Reference: RFC 9484.
IANA registered three new HTTP Capsule Types: 0x01 ADDRESS_ASSIGN, 0x02 ADDRESS_REQUEST, and 0x03 ROUTE_ADVERTISEMENT, all with permanent status and change controller IETF, in the 'HTTP Capsule Types' registry.
HTTP servers supporting IP proxying SHOULD restrict its use to authenticated users, as arbitrary clients could abuse tunnels to send traffic attributed to the proxy. Authentication mechanisms include mutual TLS, HTTP Authorization headers, or bearer tokens. Proxies can additionally rate-limit clients or restrict address assignment based on client attributes.
Optimistic sending of IP packets before receiving a successful response is not allowed in HTTP/1.x, because a server rejecting the HTTP Upgrade could attempt to parse the IP packets as a subsequent HTTP request, enabling request smuggling. An intermediary re-encoding from HTTP/2 or HTTP/3 to HTTP/1.1 MUST NOT forward received capsules until it has parsed a successful IP proxying response.
Proxies that forward ICMP on shared external IP addresses MUST inspect the invoking packet embedded in ICMP error messages and only forward the ICMP to the client whose request scope matches, to prevent one client's traffic information from being inadvertently disclosed to another client sharing the same proxy IP address.
Where an endpoint knows its peer is only allowed to send from a specific IP prefix (via out-of-band configuration or ADDRESS_ASSIGN capsules), endpoints MUST follow BCP38 recommendations to prevent source address spoofing, since IP proxying can facilitate denial-of-service attacks via falsified source addresses.
Each IP Address Range in a ROUTE_ADVERTISEMENT capsule contains: IP Version (8-bit, MUST be 4 or 6), Start IP Address (32 or 128 bits), End IP Address (32 or 128 bits, MUST be ≥ Start), and IP Protocol (8-bit; 0 means all protocols allowed; ICMP is always allowed regardless).
The Assigned Address structure used in ADDRESS_ASSIGN capsules contains: Request ID (variable-length integer), IP Version (8-bit unsigned, MUST be 4 or 6), IP Address (32 bits for IPv4, 128 bits for IPv6), and IP Prefix Length (8-bit unsigned, MUST be ≤ length of IP Address in bits). Lower bits not covered by prefix length MUST be zero.
The IP Proxying HTTP Datagram Payload consists of a Context ID (variable-length integer) followed by a Payload field. Context ID 0 is reserved for full IP packets (from IP Version field through the last byte of IP payload). Unknown Context IDs SHALL be either silently dropped or briefly buffered awaiting registration.