Filename: 365-http-connect-ext.md
Title: Extensions for HTTP CONNECT support
Author: Nick Mathewson
Created: 10 June 2025
Status: Open
Introduction and scope
The C tor implementation supports HTTP CONNECT as an alternative to SOCKS for applications to use when negotiating connections. As of this writing, we have a draft specification for C tor's current behavior
There are a few reasons to prefer HTTP CONNECT over SOCKS:
- It is more readily extensible, and supports named headers in requests and responses.
- It is supported by many applications by which SOCKS is not.
For these reasons, we'd like to add support in Arti as well. But before we do so, it would be a good idea to bring HTTP CONNECT up to par with SOCKS in terms of the features we support with it.
This proposal describes changes and extensions to our HTTP CONNECT behavior.
Changes to the spec that do not affect current behavior
All new headers will begin with "Tor-". The "X-Tor-" prefix is reserved for historical extensions, and is deprecated for the reasons explained in RFC 6648.
Changes to current HTTP CONNECT behavior
These are changes to the behavior implemented in C tor, and described in the draft specification. They should be implemented in C tor as well as Arti.
Improved error codes
END_REASON_RESOLVEFAILEDshould produce 503; currently it produces 404.END_REASON_NOROUTEshould produce 503; currently it produces 404.
Limited use of Proxy-Authorization or stream isolation
Currently we look at the Proxy-Authorization header
as a possible source of stream isolation.
This is by analogy to our use of SOCKS usernames and passwords
for stream isolation.
Ordinarily, we prefer that applications should use
the Tor-Stream-Isolation header for this purpose instead:
we only allow Proxy-Authorization in order to support
applications with janky HTTP libraries
that do not support adding arbitrary headers.
We will retain our current Proxy-Authorization behavior,
for backward compatibility;
however, we will specify that applications wishing to use this behavior
in the future SHOULD set the auth-scheme to "Basic",
with a username of tor-iso, and an arbitrary password,
all encoded as specified in RFC 7617.
We will also specify that proxies SHOULD warn if a Proxy-Authorization
in any other format is provided.
Additional features
The features in this section are meant to be proposed independently. We anticipate that, after discussion, some will be approved and some will not.
For each feature, we'll describe whether it should be implemented in Arti only, or in both Arti and C Tor.
Tor-Stream-Isolation: New header for stream isolation
(Allowed-In: Request.)
The Tor-Stream-Isolation header is introduced
as a new stream isolation key.
Its semantics are the same as X-Tor-Stream-Isolation,
whose "X-" prefix is now deprecated.
If both X-Tor-Stream-Isolation and Tor-Stream-Isolation are present, both of them serve as separate isolation keys.
Tor-RPC-Target: Arti RPC support
(Allowed-In: Request.)
We reserve the header "Tor-RPC-Target" to contain an RPC Object ID, to be used as a target for an RPC request.
Implementations SHOULD reject such requests if the target RPC object does not exist.
An implementation that generally supports Tor extensions, but that doesn't support Arti RPC, SHOULD reject requests containing this header.
(Arti should implement RPC behavior; C tor should implement "reject" behavior.)
Tor-Request-Failed Extended error codes
(Allowed-In: Response.)
When a connection closes before it can be established, we currently communicate the failure reason in the HTTP status code.
We will also include a Tor-Request-Failed header indicating
one or more reasons why the connection could not be completed.
This will be a space-separated list of tokens.
The specified members of this list will at
minimum correspond to all the current END reasons,
and all the onion-service-specific SOCKS failure codes.
(Arti only.)
Via / Server: Indication for Tor proxy protocol support
(Allowed-In: Response.)
We should specify that all implementations that support these extensions
should include a non-empty Via or Server header in their responses.
The "via" header should include the name of the software, and its version, as the comment field. In "via", the received-protocol and received-by fields should be set to "tor/1.0" and "tor-network" respectively, as in:
Via: tor/1.0 tor-network (Tor 0.4.9.4-alpha)
In "Server", we use "tor/1.0" as the product, and place the software name and version in its comment field, as in:
Server: tor/1.0 (Arti 1.7.0)
Proxies MUST NOT include this header unless they forward user traffic over anonymous Tor connections.
Clients MAY check for the presence or absence of this header.
Clients MUST NOT inspect the contents of this header
to determine whether a given feature is supported or not;
they should use Tor-Capabilities instead.
Clients MAY use this to determine whether some software has a particular bug, but the matching MUST NOT treat any future versions as buggy. (So, the bug must be fixed before this technique can be used.)
(Arti and C tor.)
OPTIONS method support
We should implement the "OPTIONS" method to check the capabilities of a proxy
without making a request.
It should return an Allow header indicating the permitted methods
(CONNECT and OPTIONS).
This feature is only useful if we also implement the
Via/Serverand/orTor-Capabilitiesresponse headers.
(Arti and C tor.)
Optimistic data support (Deferred)
As with SOCKS,
clients MAY send data after their CONNECT request,
without waiting for a reply.
Proxies MUST retain and deliver that data if the connection is successful,
and SHOULD send that data optimistically
(after the BEGIN cell, before any CONNECTED is received).
(Arti and C Tor.)
We're deferring this for now: more design is needed to avoid framing errors.
See https://gitlab.torproject.org/tpo/core/torspec/-/merge_requests/419#note_3236424 for discussion.
Tor-Family-Preference: IP version preferences
(Allowed-In: Request.)
Tor allows the client to transmit its preferences for IP versions as part of its BEGIN message.
We allow these to be encoded in an HTTP CONNECT header,
Tor-Family-Preference.
Permitted values are:
ipv4-preferred(any family allowed; ipv4 preferred)ipv6-preferred(any family allowed; ipv6 preferred)ipv4-only(only ipv4 is allowed)ipv6-only(only ipv6 is allowed)
The default is "ipv4-preferred".
Any unrecognized value SHOULD be treated as "ipv4-preferred".
(Arti only.)
Tor-Capabilities: Determining specific extensions
(Allowed-In: Response.)
In responses,
proxies SHOULD include an Tor-Capabilities header
containing a space-separated list of capabilities.
Clients MAY use this header to decide
whether a required capability is present.
All new features that we add will have a corresponding capability. Clients SHOULD use check for these capabilities whenever they are using a feature which, if absent, would be insecure.
Every request header has a capability of the same name, to indicate that the header will be recognized and processed if sent.
As an alternative, we might use something like
Tor-Require-Capabilitiesfor the client to say "don't even talk to me unless you support X." I'm not taking this alternative, though, since the default behavior of a non-tor HTTP CONNECT proxy would be exactly what we don't want here.
If we're worried about overhead from a list that will grow longer and longer over time, we could say that it MUST be sent in response to OPTIONS only.
(Arti and C Tor.)
"Bilingual" proxies: HTTP CONNECT and SOCKS on one port.
A SOCKS handshake always begins with a byte of value 4 or five. An HTTP handshake always begins with an ASCII character. Currently, in the C tor implementation, we use this property to distinguish SOCKS from HTTP connections, and we reject each kind with an appropriate error message if it arrives on the wrong port.
Instead, we could specify that there is a single "proxy port" which accepts both SOCKS and HTTP requests. This port could accept both SOCKS and "HTTP CONNECT".
Before implementing this, we should make sure it is safe.
(For what it's worth, a TLS handshake always begins with the byte 22 followed by two bytes to indicate record protocol version, so we could add support for TLS in the future if we wanted.)
(Arti only. Maybe C tor if lack of HTTP-by-default becomes a deployment issue.)