CONNECT-TCP

CONNECT-TCP is a template-driven way to request a TCP tunnel through an HTTP proxy. It identifies the proxy by a URI template and a well-known URI, then opens the tunnel with the extended CONNECT method on HTTP/2 and HTTP/3 or with an Upgrade handshake on HTTP/1.1.

Draft specification

CONNECT-TCP is defined by the httpbis working group draft draft-ietf-httpbis-connect-tcp, a standards-track item currently in working group last call. The mechanics described here reflect the current revision and may shift before publication as an RFC.

What CONNECT-TCP is

CONNECT-TCP is an HTTP mechanism for proxying a single TCP connection, where the proxy service is named by a URI template rather than by a bare host and port. A client substitutes the target host and target port into the template, sends the resulting request to the proxy, and the proxy opens a TCP connection to that target and relays bytes in both directions. The same approach works across every modern HTTP version, using extended CONNECT on HTTP/2 and HTTP/3 and a protocol upgrade on HTTP/1.1.

The design reuses standard HTTP components and semantics, so it adds no changes to the core protocol. A request carries a real target URI, the proxy endpoint lives at a discoverable path, and the tunneled payload travels through the Capsule Protocol once the connection is established. The result is a TCP tunnel that behaves like an ordinary HTTP request up to the point where byte relaying begins.

The problem it solves

CONNECT-TCP exists because the classic CONNECT method carries no configuration beyond the target host and port. A classic CONNECT request names only where the bytes should go, which leaves the proxy itself unidentified. That gap creates three practical limits.

A single HTTP server cannot host several distinct proxy services, because the server has no path or origin to tell one proxy apart from another. The missing explicit origin also removes the usual defenses against port-misdirection attacks, where a request meant for one service is steered toward another. And without a clear origin for the proxy, origin-scoped response header fields become ambiguous.

CONNECT-TCP answers each point by giving the proxy a real URI. The proxy service is identified by a URI template, the target host and port fill in the template variables, and the expanded URI carries a scheme, an authority, and a path. One server can then run many proxy services at different paths, and each request has a well-defined origin.

Relationship to classic CONNECT

CONNECT-TCP refines the classic CONNECT method rather than replacing the idea of a TCP tunnel. Classic CONNECT uses authority-form, sending CONNECT example.re:443 so the proxy learns the target directly from the request line. CONNECT-TCP instead encodes the target inside a templated request URI, which gives the proxy a path and an origin of its own.

The two coexist through a defined fallback path. A client that prefers classic CONNECT treats specific signals as a sign to switch to the registered CONNECT-TCP template. An 426 Upgrade Required response carrying Upgrade: connect-tcp on HTTP/1.1, or a 501 Not Implemented response on any version, tells the client to retry using the default template. This lets a deployment move toward the templated form while older clients keep working.

Relationship to MASQUE

CONNECT-TCP is the TCP sibling of the MASQUE tunneling protocols. MASQUE defines connect-udp for proxying single UDP flows and connect-ip for proxying raw IP packets, both described by a URI template and both built on HTTP Datagrams and the Capsule Protocol. CONNECT-TCP applies the same template-driven model to TCP, and its well-known suffix joins the MASQUE family in the same IANA registry.

The shared foundation means a proxy can offer TCP, UDP, and IP tunnels through one consistent pattern. Each protocol names its target through a template, each runs over the same HTTP connection machinery, and each reuses the Capsule Protocol for the tunneled payload. CONNECT-TCP rounds out the set so a single proxy covers the common transport layers that applications reach for.

Protocol Tunnels Template family
connect-tcp One TCP connection MASQUE URI suffix tcp
connect-udp One UDP flow MASQUE URI suffix udp
connect-ip Full IP packets MASQUE URI suffix ip

The URI template and well-known URI

CONNECT-TCP identifies a proxy with a URI template that contains two variables, target_host and target_port. The client substitutes the destination host and port into those variables to produce the request URI for a single tunnel. A proxy advertises its own template, and any template with both variables is valid, so an operator can place the proxy at any path that suits the deployment.

A registered default template gives clients a fixed fallback under the well-known URI tree:

https://$PROXY_HOST:$PROXY_PORT/.well-known/masque/tcp/{target_host}/{target_port}/

The tcp suffix is registered in the MASQUE URI Suffixes registry alongside udp and ip. A client tunneling to 192.0.2.1 on port 443 through the default template expands it to /.well-known/masque/tcp/192.0.2.1/443/ and sends the request there. A proxy with a custom template, such as https://proxy.example.re/proxy{?target_host,target_port}, encodes the same two values as query parameters instead.

Extended CONNECT with connect-tcp

On HTTP/2 and HTTP/3, CONNECT-TCP uses the extended CONNECT method with the :protocol pseudo-header set to connect-tcp. Extended CONNECT keeps the CONNECT method but adds :protocol to select the kind of tunnel, the same mechanism that carries WebSocket and the MASQUE tunnels. The server advertises support by sending the SETTINGS_ENABLE_CONNECT_PROTOCOL setting.

The request carries a full set of pseudo-headers derived from the expanded template rather than a bare authority:

Pseudo-header Value
:method CONNECT
:protocol connect-tcp
:scheme The scheme from the expanded URI, usually https
:authority The proxy's host and port
:path The expanded template path carrying the target

The proxy accepts the tunnel with a 2xx response. After that point the stream stops behaving like a normal response body and starts carrying the tunneled TCP data. The Capsule-Protocol: ?1 field marks the stream as Capsule Protocol content, and TCP payload bytes travel inside DATA and FINAL_DATA capsules whose ordered concatenation reproduces the TCP byte stream.

CONNECT-TCP on HTTP/1.1

On HTTP/1.1, CONNECT-TCP runs over a protocol upgrade because HTTP/1.1 has no extended CONNECT. The client sends a GET request whose target is the expanded template URI, along with Connection: Upgrade and Upgrade: connect-tcp. The proxy confirms the switch with 101 Switching Protocols, and the connection then carries the tunneled TCP data.

GET /proxy?target_host=192.0.2.1&target_port=443 HTTP/1.1
Host: proxy.example.re
Connection: Upgrade
Upgrade: connect-tcp
Capsule-Protocol: ?1

The HTTP/1.1 form and the extended CONNECT form describe the same tunnel through the same template, so a proxy serves both with one configuration. A client that meets a 426 Upgrade Required response carrying Upgrade: connect-tcp, or a 501 Not Implemented response, learns that the templated form is the path to use and retries accordingly.

Example

A client establishes a CONNECT-TCP tunnel to 2001:db8::1 on port 443 through a proxy over HTTP/2. The client expands the proxy's URI template with the target host and port, percent-encoding the IPv6 address for the query. The request uses extended CONNECT, so the :protocol pseudo-header selects the TCP tunnel and the :path carries the expanded target.

Request

HEADERS
:method = CONNECT
:protocol = connect-tcp
:scheme = https
:authority = request-proxy.example.re
:path = /proxy?target_host=2001%3Adb8%3A%3A1&target_port=443
capsule-protocol = ?1

The proxy opens a TCP connection to the target and accepts the tunnel with a 2xx response.

Response

HEADERS
:status = 200
capsule-protocol = ?1

Once the tunnel is open, TCP payload bytes travel inside DATA capsules in both directions, with a FINAL_DATA capsule marking the end of the byte stream. The same HTTP/2 connection continues to serve other streams in parallel, so the tunnel multiplexes alongside ordinary requests.

See also

Last updated: June 5, 2026