<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.2 (Ruby 2.6.4) -->
<?rfc-ext html-pretty-print="prettyprint https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"?>
<rfc xmlns:x="http://purl.org/net/xml2rfc/ext"
      category="std"
      consensus="true"
      docName="draft-ietf-httpbis-connect-tcp-00"
      ipr="trust200902"
      sortRefs="true"
      submissionType="IETF"
      symRefs="true"
      tocInclude="true">
   <x:feedback template="mailto:ietf-http-wg@w3.org?subject={docname},%20%22{section}%22\&amp;amp;body=%3c{ref}%3e:"/>
   <front>
      <title abbrev="Templated CONNECT-TCP">Template-Driven HTTP CONNECT Proxying for TCP</title>
      <author fullname="Benjamin M. Schwartz" initials="B. M." surname="Schwartz">
         <organization>Meta Platforms, Inc.</organization>
         <address>
            <email>ietf@bemasc.net</email>
         </address>
      </author>
      <date day="17" month="May" year="2023"/>
      <area>art</area>
      <workgroup>httpbis</workgroup>
      <keyword>Internet-Draft</keyword>
      <abstract><?line 31?>
         <t>TCP proxying using HTTP CONNECT has long been part of the core HTTP specification. However, this proxying functionality has several important deficiencies in modern HTTP environments. This specification defines an alternative HTTP proxy service configuration for TCP connections. This configuration is described by a URI Template, similar to the CONNECT-UDP and CONNECT-IP protocols.</t>
      </abstract>
   </front>
   <middle><?line 35?>
      <section anchor="introduction">
         <name>Introduction</name>
         <section anchor="history">
            <name>History</name>
            <t>HTTP has used the CONNECT method for proxying TCP connections since HTTP/1.1. When using CONNECT, the request target specifies a host and port number, and the proxy forwards TCP payloads between the client and this destination (<xref section="9.3.6" sectionFormat="comma" target="RFC9110"/>). To date, this is the only mechanism defined for proxying TCP over HTTP. In this specification, this is referred to as a "classic HTTP CONNECT proxy".</t>
            <t>HTTP/3 uses a UDP transport, so it cannot be forwarded using the pre-existing CONNECT mechanism. To enable forward proxying of HTTP/3, the MASQUE effort has defined proxy mechanisms that are capable of proxying UDP datagrams <xref target="RFC9298"/>, and more generally IP datagrams <xref target="I-D.ietf-masque-connect-ip"/>. The destination host and port number (if applicable) are encoded into the HTTP resource path, and end-to-end datagrams are wrapped into HTTP Datagrams <xref target="RFC9297"/> on the client-proxy path.</t>
         </section>
         <section anchor="problems">
            <name>Problems</name>
            <t>Classic HTTP CONNECT proxies are identified by an origin. The proxy does not have a path of its own. This prevents any origin from hosting multiple distinct proxy services.</t>
            <t>Ordinarily, HTTP allows multiple origin hostnames to share a single server IP address and port number (i.e., virtual-hosting), by specifying the applicable hostname in the "Host" or ":authority" header field. However, classic HTTP CONNECT proxies use these fields to indicate the CONNECT request's destination (<xref section="3.2.3" sectionFormat="comma" target="RFC9112"/>), leaving no way to determine the proxy's origin from the request. As a result, classic HTTP CONNECT proxies cannot be deployed using virtual-hosting, nor can they apply the usual defenses against server port misdirection attacks (see <xref section="7.4" sectionFormat="of" target="RFC9110"/>).</t>
            <t>Classic HTTP CONNECT proxies can be used to reach a target host that is specified as a domain name or an IP address. However, because only a single target host can be specified, proxy-driven Happy Eyeballs and cross-IP fallback can only be used when the host is a domain name. For IP-targeted requests to succeed, the client must know which address families are supported by the proxy via some out-of-band mechanism, or open multiple independent CONNECT requests and abandon any that prove unnecessary.</t>
         </section>
         <section anchor="overview">
            <name>Overview</name>
            <t>This specification describes an alternative mechanism for proxying TCP in HTTP. Like <xref target="RFC9298"/> and <xref target="I-D.ietf-masque-connect-ip"/>, the proxy service is identified by a URI Template. Proxy interactions reuse standard HTTP components and semantics, avoiding changes to the core HTTP protocol.</t>
         </section>
      </section>
      <section anchor="conventions-and-definitions">
         <name>Conventions and Definitions</name>
         <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>", "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"/>
            <xref target="RFC8174"/> when, and only when, they appear in all capitals, as shown here.</t>
         <?line -18?>
      </section>
      <section anchor="specification">
         <name>Specification</name>
         <t>A template-driven TCP transport proxy for HTTP is identified by a URI Template <xref target="RFC6570"/> containing variables named "target_host" and "tcp_port". The client substitutes the destination host and port number into these variables to produce the request URI.</t>
         <t>The "target_host" variable <bcp14>MUST</bcp14> be a domain name, an IP address literal, or a list of IP addresses. The "tcp_port" variable <bcp14>MUST</bcp14> be a single integer. If "target_host" is a list (as in <xref section="2.4.2" sectionFormat="of" target="RFC6570"/>), the server <bcp14>SHOULD</bcp14> perform the same connection procedure as if these addresses had been returned in response to A and AAAA queries for a domain name.</t>
         <section anchor="in-http11">
            <name>In HTTP/1.1</name>
            <t>In HTTP/1.1, the client uses the proxy by issuing a request as follows:</t>
            <t>
               <list style="symbols">
                  <t>The method <bcp14>SHALL</bcp14> be "GET".</t>
                  <t>The request <bcp14>SHALL</bcp14> include a single Host header field containing the origin of the proxy.</t>
                  <t>The request <bcp14>SHALL</bcp14> include a Connection header field with the value "Upgrade". (Note that this requirement is case-insensitive as per <xref section="7.6.1" sectionFormat="of" target="RFC9110"/>.)</t>
                  <t>The request <bcp14>SHALL</bcp14> include an "Upgrade" header field with the value "connect-tcp".</t>
                  <t>The request's target <bcp14>SHALL</bcp14> correspond to the URI derived from expansion of the proxy's URI Template.</t>
               </list>
            </t>
            <t>If the request is well-formed and permissible, the proxy <bcp14>MUST</bcp14> attempt the TCP connection before returning its response header. If the TCP connection is successful, the response <bcp14>SHALL</bcp14> be as follows:</t>
            <t>
               <list style="symbols">
                  <t>The HTTP status code <bcp14>SHALL</bcp14> be 101 (Switching Protocols).</t>
                  <t>The response <bcp14>SHALL</bcp14> include a Connection header field with the value "Upgrade".</t>
                  <t>The response <bcp14>SHALL</bcp14> include a single Upgrade header field with the value "connect-tcp".</t>
               </list>
            </t>
            <t>If the request is malformed or impermissible, the proxy <bcp14>MUST</bcp14> return a 4XX error code. If a TCP connection was not established, the proxy <bcp14>MUST NOT</bcp14> switch protocols to "connect-tcp", and the client <bcp14>MAY</bcp14> reuse this connection for additional HTTP requests.</t>
            <t>After a success response is returned, the connection <bcp14>SHALL</bcp14> conform to all the usual requirements for classic CONNECT proxies in HTTP/1.1 (<xref section="9.3.6" sectionFormat="comma" target="RFC9110"/>). Additionally, if the proxy observes a connection error from the client (e.g., a TCP RST, TCP timeout, or TLS error), it <bcp14>SHOULD</bcp14> send a TCP RST to the target. If the proxy observes a connection error from the target, it <bcp14>SHOULD</bcp14> send a TLS "internal_error" alert to the client, or set the TCP RST bit if TLS is not in use.</t>
            <figure title="Templated TCP proxy example in HTTP/1.1">
               <artwork>
Client                                                 Proxy

GET /proxy?target_host=192.0.2.1&amp;tcp_port=443 HTTP/1.1
Host: example.com
Connection: Upgrade
Upgrade: connect-tcp

** Proxy establishes a TCP connection to 192.0.2.1:443 **

                            HTTP/1.1 101 Switching Protocols
                            Connection: Upgrade
                            Upgrade: connect-tcp
</artwork>
            </figure>
         </section>
         <section anchor="in-http2-and-http3">
            <name>In HTTP/2 and HTTP/3</name>
            <t>In HTTP/2 and HTTP/3, the client uses the proxy by issuing an "extended CONNECT" request as follows:</t>
            <t>
               <list style="symbols">
                  <t>The :method pseudo-header field <bcp14>SHALL</bcp14> be "CONNECT".</t>
                  <t>The :protocol pseudo-header field <bcp14>SHALL</bcp14> be "connect-tcp".</t>
                  <t>The :authority pseudo-header field <bcp14>SHALL</bcp14> contain the authority of the proxy.</t>
                  <t>The :path and :scheme pseudo-header fields <bcp14>SHALL</bcp14> contain the path and scheme of the request URI derived from the proxy's URI Template.</t>
               </list>
            </t>
            <t>From this point on, the request and response <bcp14>SHALL</bcp14> conform to all the usual requirements for classic CONNECT proxies in this HTTP version (see <xref section="8.5" sectionFormat="of" target="RFC9113"/> and <xref section="4.4" sectionFormat="of" target="RFC9114"/>).</t>
            <figure title="Templated TCP proxy example in HTTP/2">
               <artwork>
HEADERS
:method = CONNECT
:scheme = https
:authority = request-proxy.example
:path = /proxy?target_host=192.0.2.1,2001:db8::1&amp;tcp_port=443
:protocol = connect-tcp
...
</artwork>
            </figure>
         </section>
      </section>
      <section anchor="additional-connection-setup-behaviors">
         <name>Additional Connection Setup Behaviors</name>
         <t>This section discusses some behaviors that are permitted or recommended in order to enhance the performance or functionality of connection setup.</t>
         <section anchor="latency-optimizations">
            <name>Latency optimizations</name>
            <t>When using this specification in HTTP/2 or HTTP/3, clients <bcp14>MAY</bcp14> start sending TCP stream content without waiting for an HTTP response. Proxies <bcp14>MUST</bcp14> buffer this "false start" content until the TCP stream becomes writable, and discard it if the TCP connection fails. (This "false start" behavior is not permitted in HTTP/1.1 because it would prevent reuse of the connection after an error response such as 407 (Proxy Authentication Required).)</t>
            <t>Servers that host a proxy under this specification <bcp14>MAY</bcp14> offer support for TLS early data in accordance with <xref target="RFC8470"/>. Clients <bcp14>MAY</bcp14> send "connect-tcp" requests in early data, and <bcp14>MAY</bcp14> include "false start" content in early data (in HTTP/2 and HTTP/3). Proxies <bcp14>MAY</bcp14> accept, reject, or delay processing of this early data. For example, a proxy with limited anti-replay defenses might choose to perform DNS resolution of the <spanx style="verb">target_host</spanx> when a request arrives in early data, but delay the TCP connection until the TLS handshake completes.</t>
         </section>
         <section anchor="conveying-metadata">
            <name>Conveying metadata</name>
            <t>This specification supports the "Expect: 100-continue" request header (<xref section="10.1.1" sectionFormat="comma" target="RFC9110"/>) in any HTTP version. The "100 (Continue)" status code confirms receipt of a request at the proxy without waiting for the proxy-destination TCP handshake to succeed or fail. This might be particularly helpful when the destination host is not responding, as TCP handshakes can hang for several minutes before failing. Implementation of "100 (Continue)" support is <bcp14>OPTIONAL</bcp14> for clients and <bcp14>REQUIRED</bcp14> for proxies.</t>
            <t>Proxies implementing this specification <bcp14>SHOULD</bcp14> include a Proxy-Status response header <xref target="RFC9209"/> in any success or failure response (i.e., status codes 101, 2XX, 4XX, or 5XX) to support advanced client behaviors and diagnostics. In HTTP/2 or HTTP/3, proxies <bcp14>MAY</bcp14> additionally send a Proxy-Status trailer in the event of an unclean shutdown.</t>
         </section>
      </section>
      <section anchor="applicability">
         <name>Applicability</name>
         <section anchor="servers">
            <name>Servers</name>
            <t>For server operators, template-driven TCP proxies are particularly valuable in situations where virtual-hosting is needed, or where multiple proxies must share an origin. For example, the proxy might benefit from sharing an HTTP gateway that provides DDoS defense, performs request sanitization, or enforces user authorization.</t>
            <t>The URI template can also be structured to generate high-entropy Capability URLs <xref target="CAPABILITY"/>, so that only authorized users can discover the proxy service.</t>
         </section>
         <section anchor="clients">
            <name>Clients</name>
            <t>Clients that support both classic HTTP CONNECT proxies and template-driven TCP proxies <bcp14>MAY</bcp14> accept both types via a single configuration string. If the configuration string can be parsed as a URI Template containing the required variables, it is a template-driven TCP proxy. Otherwise, it is presumed to represent a classic HTTP CONNECT proxy.</t>
         </section>
         <section anchor="multi-purpose-proxies">
            <name>Multi-purpose proxies</name>
            <t>The names of the variables in the URI Template uniquely identify the capabilities of the proxy. Undefined variables are permitted in URI Templates, so a single template can be used for multiple purposes.</t>
            <t>Multipurpose templates can be useful when a single client may benefit from access to multiple complementary services (e.g., TCP and UDP), or when the proxy is used by a variety of clients with different needs.</t>
            <figure title="Example multipurpose template for a combined TCP, UDP, and IP proxy and DoH server">
               <artwork>
https://proxy.example/{?target_host,tcp_port,target_port,
                        target,ipproto,dns}
</artwork>
            </figure>
         </section>
      </section>
      <section anchor="security-considerations">
         <name>Security Considerations</name>
         <t>TODO</t>
      </section>
      <section anchor="operational-considerations">
         <name>Operational Considerations</name>
         <t>Templated TCP proxies can make use of standard HTTP gateways and path-routing to ease implementation and allow use of shared infrastructure. However, current gateways might need modifications to support TCP proxy services. To be compatible, a gateway must:</t>
         <t>
            <list style="symbols">
               <t>support Extended CONNECT.</t>
               <t>convert HTTP/1.1 Upgrade requests into Extended CONNECT.</t>
               <t>allow the Extended CONNECT method to pass through to the origin.</t>
               <t>forward Proxy-* request headers to the origin.</t>
            </list>
         </t>
      </section>
      <section anchor="iana-considerations">
         <name>IANA Considerations</name>
         <t>IF APPROVED, IANA is requested to add the following entry to the HTTP Upgrade Token Registry:</t>
         <t>
            <list style="symbols">
               <t>Value: "connect-tcp"</t>
               <t>Description: Proxying of TCP payloads</t>
               <t>Reference: (This document)</t>
            </list>
         </t>
      </section>
   </middle>
   <back>
      <references anchor="sec-normative-references" title="Normative References">
         <reference anchor="RFC9110">
            <front>
               <title>HTTP Semantics</title>
               <author fullname="R. Fielding"
                        initials="R."
                        role="editor"
                        surname="Fielding"/>
               <author fullname="M. Nottingham"
                        initials="M."
                        role="editor"
                        surname="Nottingham"/>
               <author fullname="J. Reschke"
                        initials="J."
                        role="editor"
                        surname="Reschke"/>
               <date month="June" year="2022"/>
            </front>
            <seriesInfo name="STD" value="97"/>
            <seriesInfo name="RFC" value="9110"/>
            <seriesInfo name="DOI" value="10.17487/RFC9110"/>
         </reference>
         <reference anchor="RFC2119">
            <front>
               <title>Key words for use in RFCs to Indicate Requirement Levels</title>
               <author fullname="S. Bradner" initials="S." surname="Bradner"/>
               <date month="March" year="1997"/>
            </front>
            <seriesInfo name="BCP" value="14"/>
            <seriesInfo name="RFC" value="2119"/>
            <seriesInfo name="DOI" value="10.17487/RFC2119"/>
         </reference>
         <reference anchor="RFC8174">
            <front>
               <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
               <author fullname="B. Leiba" initials="B." surname="Leiba"/>
               <date month="May" year="2017"/>
            </front>
            <seriesInfo name="BCP" value="14"/>
            <seriesInfo name="RFC" value="8174"/>
            <seriesInfo name="DOI" value="10.17487/RFC8174"/>
         </reference>
         <reference anchor="RFC6570">
            <front>
               <title>URI Template</title>
               <author fullname="J. Gregorio" initials="J." surname="Gregorio"/>
               <author fullname="R. Fielding" initials="R." surname="Fielding"/>
               <author fullname="M. Hadley" initials="M." surname="Hadley"/>
               <author fullname="M. Nottingham" initials="M." surname="Nottingham"/>
               <author fullname="D. Orchard" initials="D." surname="Orchard"/>
               <date month="March" year="2012"/>
            </front>
            <seriesInfo name="RFC" value="6570"/>
            <seriesInfo name="DOI" value="10.17487/RFC6570"/>
         </reference>
         <reference anchor="RFC9113">
            <front>
               <title>HTTP/2</title>
               <author fullname="M. Thomson"
                        initials="M."
                        role="editor"
                        surname="Thomson"/>
               <author fullname="C. Benfield"
                        initials="C."
                        role="editor"
                        surname="Benfield"/>
               <date month="June" year="2022"/>
            </front>
            <seriesInfo name="RFC" value="9113"/>
            <seriesInfo name="DOI" value="10.17487/RFC9113"/>
         </reference>
         <reference anchor="RFC9114">
            <front>
               <title>HTTP/3</title>
               <author fullname="M. Bishop"
                        initials="M."
                        role="editor"
                        surname="Bishop"/>
               <date month="June" year="2022"/>
            </front>
            <seriesInfo name="RFC" value="9114"/>
            <seriesInfo name="DOI" value="10.17487/RFC9114"/>
         </reference>
         <reference anchor="RFC8470">
            <front>
               <title>Using Early Data in HTTP</title>
               <author fullname="M. Thomson" initials="M." surname="Thomson"/>
               <author fullname="M. Nottingham" initials="M." surname="Nottingham"/>
               <author fullname="W. Tarreau" initials="W." surname="Tarreau"/>
               <date month="September" year="2018"/>
            </front>
            <seriesInfo name="RFC" value="8470"/>
            <seriesInfo name="DOI" value="10.17487/RFC8470"/>
         </reference>
         <reference anchor="RFC9209">
            <front>
               <title>The Proxy-Status HTTP Response Header Field</title>
               <author fullname="M. Nottingham" initials="M." surname="Nottingham"/>
               <author fullname="P. Sikora" initials="P." surname="Sikora"/>
               <date month="June" year="2022"/>
            </front>
            <seriesInfo name="RFC" value="9209"/>
            <seriesInfo name="DOI" value="10.17487/RFC9209"/>
         </reference>
      </references>
      <references anchor="sec-informative-references" title="Informative References">
         <reference anchor="CAPABILITY" target="https://www.w3.org/TR/capability-urls/">
            <front>
               <title>Good Practices for Capability URLs</title>
               <author/>
               <date month="February" year="2014"/>
            </front>
         </reference>
         <reference anchor="RFC9298">
            <front>
               <title>Proxying UDP in HTTP</title>
               <author fullname="D. Schinazi" initials="D." surname="Schinazi"/>
               <date month="August" year="2022"/>
            </front>
            <seriesInfo name="RFC" value="9298"/>
            <seriesInfo name="DOI" value="10.17487/RFC9298"/>
         </reference>
         <reference anchor="I-D.ietf-masque-connect-ip">
            <front>
               <title>Proxying IP in HTTP</title>
               <author fullname="Tommy Pauly" initials="T." surname="Pauly">
                  <organization>Apple Inc.</organization>
               </author>
               <author fullname="David Schinazi" initials="D." surname="Schinazi">
                  <organization>Google LLC</organization>
               </author>
               <author fullname="Alex Chernyakhovsky"
                        initials="A."
                        surname="Chernyakhovsky">
                  <organization>Google LLC</organization>
               </author>
               <author fullname="Mirja Kühlewind" initials="M." surname="Kühlewind">
                  <organization>Ericsson</organization>
               </author>
               <author fullname="Magnus Westerlund" initials="M." surname="Westerlund">
                  <organization>Ericsson</organization>
               </author>
               <date day="28" month="April" year="2023"/>
            </front>
            <seriesInfo name="Internet-Draft" value="draft-ietf-masque-connect-ip-13"/>
         </reference>
         <reference anchor="RFC9297">
            <front>
               <title>HTTP Datagrams and the Capsule Protocol</title>
               <author fullname="D. Schinazi" initials="D." surname="Schinazi"/>
               <author fullname="L. Pardue" initials="L." surname="Pardue"/>
               <date month="August" year="2022"/>
            </front>
            <seriesInfo name="RFC" value="9297"/>
            <seriesInfo name="DOI" value="10.17487/RFC9297"/>
         </reference>
         <reference anchor="RFC9112">
            <front>
               <title>HTTP/1.1</title>
               <author fullname="R. Fielding"
                        initials="R."
                        role="editor"
                        surname="Fielding"/>
               <author fullname="M. Nottingham"
                        initials="M."
                        role="editor"
                        surname="Nottingham"/>
               <author fullname="J. Reschke"
                        initials="J."
                        role="editor"
                        surname="Reschke"/>
               <date month="June" year="2022"/>
            </front>
            <seriesInfo name="STD" value="99"/>
            <seriesInfo name="RFC" value="9112"/>
            <seriesInfo name="DOI" value="10.17487/RFC9112"/>
         </reference>
      </references>
      <?line 204?>
      <section anchor="acknowledgments" numbered="false">
         <name>Acknowledgments</name>
         <t>Thanks to Amos Jeffries and Tommy Pauly for close review and suggested changes.</t>
      </section>
   </back>
</rfc>
