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
- Template-Driven HTTP CONNECT-TCP (draft-ietf-httpbis-connect-tcp)
- RFC 9297: HTTP Datagrams and the Capsule Protocol
- RFC 6570: URI Template
- CONNECT
- MASQUE
- Protocol upgrade
- HTTP connection
- Well-known URIs
- HTTP/2
- HTTP/3
- HTTP headers