Comparing ALPS and Half-RTT Data
Google LLC
davidben@google.com
General
TLS
This document compares the Application Layer Protocols Settings extension with
the half-RTT feature in TLS 1.3.
Introduction
An application-layer protocol often starts with both parties
negotiating parameters under which the protocol operates; for
instance, HTTP/2 and HTTP/3 use a SETTINGS
frame to exchange the list of protocol parameters supported by each endpoint.
This can achieved by waiting for TLS handshake to complete and then
performing the application-layer handshake within the application protocol
itself.
This approach, however, means application protocols must wait for a secondary
negotiation to complete, often incurring network round-trip. HTTP/2 and HTTP/3
mitigate this with a best-effort negotiation scheme: clients do not wait for
server SETTINGS before sending a request. But then, by the time the client
applies the setting, it has already sent the first request based on the default
values. This limits the kinds of extensions possible. For example, the SETTINGS
frame cannot support negotiate header compression or a different
static table without changing the protocol to disable compression
by default and switch partway through.
Protocol selection is another example of application-level negotiation with
these trade-offs. The Application Layer Protocol Negotiation (ALPN) extension
adds protocol selection into the TLS handshake. ALPN is instead
consistently ordered before all application data, including TLS 1.3 early data,
without either a round-trip penalty or the need to send initial pre-negotiation
data (see Section 3.2 of ).
The Application Layer Protocol Settings (ALPS) extension
implements and adds a similar mechanism for settings
within the protocol. It sends ALPN-specific protocol settings strings in the
handshake, which can be ordered correctly relative to application data and
integrated with TLS 1.3 early data negotiation.
As an alternative, Section 4.4.4 of allows a server to send
application data after the server Finished message, often referred to as
half-RTT data. Half-RTT data is not a complete solution to the settings problem,
however. This document describes the other changes necessary and compares the
approach to ALPS.
Using Half-RTT Data
Although not currently widely-implemented, half-RTT data can be used to deliver
HTTP/2 SETTINGS and other values at the right round-trip. This would result in
a handshake flow like the following.
ServerHello
...
{Finished}
<-------- [HTTP/2 SETTINGS]
...
{Finished}
[HTTP/2 SETTINGS] -------->
[HTTP/2 requests] <-------> [HTTP/2 responses]
]]>
The approach, however, requires a number of additional changes and protocol
interactions to work correctly.
Half-RTT Delimiter
In this design, the client waits to receive the HTTP/2 SETTINGS frame before
sending requests. However, HTTP/2 servers are not required to send SETTINGS in
half-data today, and most existing ones do not. [[TODO: Did I ever write this
down anywhere I can link to? When I probed TLS 1.3 HTTP/2 servers, I found none
that send half-RTT data.]] Without a new signal to the client, waiting would
add a latency penalty to existing servers. TLS 1.3 does not include a delimiter
between half-RTT data and the rest of the server application stream, so the
client does not know a priori when it is done reading.
One option would be a TLS extension that adds a delimiter between half-RTT and
normal server application data. The client would then wait for that delimiter
without round-trip penalty and proceed. This would not work in QUIC because QUIC
does not use TLS for application data at all. Instead, half-RTT data would need
to be lifted into the handshake, which is the ALPS extension.
Alternatively, the client could rely on application protocol semantics, and
assume the protocol defines exactly what is sent in half-RTT. However, HTTP/2
does not do this today. This would require defining new HTTP/2.1 and HTTP/3.1
protocols with a MUST-level requirement to send half-RTT SETTINGS. HTTP/2.1 and
HTTP/3.1 would be negotiated via ALPN. Note both HTTP/2 and HTTP/3 must be
updated because, per Section 3.2 of , connectivity
problems can break QUIC and clients are encouraged to fall back to a TCP-based
version of HTTP.
Non-Integer HTTP Settings
The HTTP/2 and HTTP/3 SETTINGS frame can only carry integer values, but
extensions may need to carry variable-length data. For example,
uses a string value.
proposes an EXTENDED_SETTINGS frame to
fix this. If defining HTTP/2.1 and HTTP/3.1, EXTENDED_SETTINGS can be added as a
mandatory component of the new protocols.
If EXTENDED_SETTINGS is left optional, the client needs to know whether to
expect a half-RTT EXTENDED_SETTINGS frame after half-RTT SETTINGS, to avoid the
issues discussed in . Thus SETTINGS would need to contain a
SETTINGS_EXTENDED_SETTINGS setting to indicate more half-RTT frames are coming.
suggested tabling EXTENDED_SETTINGS in favor of
extensions defining new HTTP frames. That would not work here, absent each
extension additionally defining an analog to SETTINGS_EXTENDED_SETTINGS, to
signal to the client to expect a new frame.
Early Data and Session Tickets
TLS 1.3 introduces early data, which allows clients to send application data
before receiving a ServerHello from the server. describes how to use
it in HTTP.
Application-level connection properties additionally must be established before
the client sends early data. Otherwise if, for instance, HPACK static tables are
negotiated, the client will not be able to encode the early request. Note
Section 2 of says early data in HTTP is conceptually concatenated
with other application data, so early data and 1-RTT data in HTTP must share
decoding rules.
Early data is sent before any response from the server, so connection properties
are typically carried over from the ticket. Section 4.2.10 of
describes the mechanism for the ALPN extension: Each PSK has an associated ALPN
protocol, determined from the previous connection. The client sends early data
assuming that protocol was used. If the server negotiates a different value, it
rejects early data.
Reliably-ordered protocol settings would require a similar construction. However
TLS does not define ALPN's early data behavior generally, so every application
protocol would need to define it themselves and, when implementing, rely on
various callback interfaces in the TLS implementation.
This also introduces a dependency between NewSessionTicket and the server
application data stream: the NewSessionTicket is not meaningful without part of
the server application data (here, the SETTINGS and EXTENDED_SETTINGS frames).
Moreover, in QUIC and DTLS, post-handshake messages are not ordered relative to
application data, so the client may receive NewSessionTicket messages in the
wrong order. The client then cannot store sessions in the TLS session until some
application-defined point. This requires further integration between TLS and the
application protocol.
See related discussion in , , and . Note
HTTP/3 addressed the ordering issue by making associating settings with the
ticket optional on the client , while a solution to this problem
makes it mandatory.
Client Certificates
TLS APIs are often structured around the following sequence of operations:
- The calling application configures TLS parameters. This may include preferred
cipher suites, client certificate requirements, callbacks to defer some
configuration, etc.
- The calling application runs the handshake to some notion of completion.
Before the handshake completes, connection properties are not established,
the peer is not authenticated, and the application does not read or write
data.
- The calling application queries handshake properties. It may query the
negotiated ALPN protocol to determine how to proceed in the application
protocol. It may query the peer certificate for application-level access
checks.
- The calling application reads and writes data according to the application
protocol.
This is analogous to many TCP socket APIs, where there is a "connect" or
"accept" operation that completes before "recv" and "send" operations are
available.
In server connections that do not resume a session, the TLS 1.3 half-RTT point
has different semantics from a complete TLS handshake. The client's identity has
not been established yes, so TLS implementations cannot transparently report the
connection as ready to the calling application. Doing so risks security issues
(the application's client certificate requirements are not yet checked) and
compatibility breaks (the application cannot usefully query the peer
certificate).
Instead, the TLS implementation might expose a separate interface for an earlier
partial completion state. The application would then write half-RTT data,
knowing that client authentication requirements are not yet met. This
complicates the interface and the above structure. Alternatively, the TLS
implementation may require the application configure a byte string to send as
half-RTT data during the handshake, but note this risks the deadlocks described
in .
TLS Terminators
Some server deployments use a TLS terminator which then makes a TCP connection
to some backend application server. These deployments would need to
preserve any MUST-level requirements to send SETTINGS in half-RTT data. A TLS
terminator which completes the handshake and then proxies data from the backend
server would inadvertently add a round-trip delay to the SETTINGS frame,
delaying HTTP requests. However, a TLS terminator which begins proxying data at
the half-RTT point instead risks skipping client certificate authentication.
Instead, the TLS terminator must coordinate with the backend server to determine
what data may be sent early to unauthenticated clients, and what data is bulk
application traffic.
TCP Flow Control
If not implemented properly, this design risks deadlocks with TCP flow control
. It is possible for both the client Finished flight and the server
half-RTT data to exceed transport buffers. The server must read the client
Finished flight and complete the handshake, even if the half-RTT data has not
been written to the wire.
In particular, a TLS implementation may try to avoid the issues in
by treating half-RTT as a configured string sent as
part of the handshake, rather than exposing a writable stream to the calling
application. This strategy must still write half-RTT data in parallel with
completing the handshake to avoid a deadlock. Many TLS implementations are
layered on top of non-blocking TCP socket APIs, which means the calling
application would still be responsible for driving these parallel operations.
This changes the I/O patterns the application expects from TLS.
Using ALPS
The ALPS strategy is described in and
. It implements , sending
application settings in the EncryptedExtensions on both client and server. The
client half is not strictly necessary (TLS 1.3 is always writable on the client
first), but simplifies server implementations in QUIC, where application data
streams are not ordered relative to each other.
ServerHello
{EncryptedExtensions}
+ alps(HTTP/2 SETTINGS)
...
<-------- {Finished}
{EncryptedExtensions}
+ alps(HTTP/2 SETTINGS)
...
{Finished}
[HTTP/2 requests] <-------> [HTTP/2 responses]
]]>
Half-RTT Delimiter
ALPS does not require a half-RTT delimiter. The entire payload is sent in the
EncryptedExtensions message, which includes a common framing for extension
values.
Non-Integer HTTP Settings
As in half-RTT data, an ALPS mechanism for HTTP/2 and HTTP/3 must handle the
SETTINGS frame limitations. allows the ALPS payload to
contain multiple frames, so either the
or strategies may be used. The payload is already framed in
EncryptedExtensions, so there is no need for an indicator value like
SETTINGS_EXTENDED_SETTINGS.
Early Data and Session Tickets
As in the half-RTT strategy, ALPS requires early data and session ticket
integration. However, this behavior is part of the extension itself, so, like
ALPN, there is no need to specify and implement this additional logic for each
application protocol.
Unlike the application-level integration for half-RTT data, this TLS-level
integration for ALPS does not have ordering issues with NewSessionTicket.
NewSessionTicket messages are ordered relative to the handshake, so the ALPS
values will always be available before a NewSessionTicket.
Client Certificates
As in ALPN and the half-RTT strategy, the server ALPS value is sent before
receiving the client certificate. In ALPS, this would be part of the extension
semantics exposed to application protocols, just as ALPN configuration is not
protected by client certificates.
TLS Terminators
As in the half-RTT solution, ALPS requires a TLS terminator deployment to
coordinate with its backend server to separate the early, unauthenticated
SETTINGS data from the rest of the stream. However, the payload is already
naturally kept separate from the rest of the application stream. Instead, the
settings values are an analog of the ALPN value, which already requires
coordination.
TCP Flow Control
ALPS sends the settings values in-band in the TLS handshake, rather than
afterwards, so the deadlock risks described in do not apply. The
client will read the entire EncryptedExtensions message (and more) before
trying to send the client Certificate, CertificateVerify, and Finished.
Security Considerations
Any server information delivered in time for the client's first application
data records must be sent before checking client certificates.
and discuss strategies for
ensuring the calling application does not inadvertently reveal sensitive
information to unauthenticated clients.
IANA Considerations
This document has no IANA considerations.
Informative References
Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension
This document describes a Transport Layer Security (TLS) extension for application-layer protocol negotiation within the TLS handshake. For instances in which multiple application protocols are supported on the same TCP or UDP port, this extension allows the application layer to negotiate which protocol will be used within the TLS connection.
Hypertext Transfer Protocol Version 2 (HTTP/2)
This specification describes an optimized expression of the semantics of the Hypertext Transfer Protocol (HTTP), referred to as HTTP version 2 (HTTP/2). HTTP/2 enables a more efficient use of network resources and a reduced perception of latency by introducing header field compression and allowing multiple concurrent exchanges on the same connection. It also introduces unsolicited push of representations from servers to clients.
This specification is an alternative to, but does not obsolete, the HTTP/1.1 message syntax. HTTP's existing semantics remain unchanged.
The Transport Layer Security (TLS) Protocol Version 1.3
This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.
This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.
Using Early Data in HTTP
Using TLS early data creates an exposure to the possibility of a replay attack. This document defines mechanisms that allow clients to communicate with servers about HTTP requests that are sent in early data. Techniques are described that use these mechanisms to mitigate the risk of replay.
HTTP/2 Extended SETTINGS Extension
HTTP/2 defines the SETTINGS frame to contain a single 32-bit value per setting. While this is sufficient to convey everything used in the core HTTP/2 specification, some protocols will require more complex values, such as arrays of code-points or strings. For such protocols, this extension defines a parallel to the SETTINGS frame, EXTENDED_SETTINGS, where the value of a setting is not a 32-bit value, but a variable-length opaque data blob whose interpretation is subject entirely to the definition of the protocol using it.
Client Hint Reliability
This document defines the Critical-CH HTTP response header, and the ACCEPT_CH HTTP/2 and HTTP/3 frames to allow HTTP servers to reliably specify their Client Hint preferences, with minimal performance overhead. Discussion Venues This note is to be removed before publishing as an RFC. Source for this draft and an issue tracker can be found at https://github.com/davidben/http-client-hint-reliability.
Hypertext Transfer Protocol Version 3 (HTTP/3)
The QUIC transport protocol has several features that are desirable in a transport for HTTP, such as stream multiplexing, per-stream flow control, and low-latency connection establishment. This document describes a mapping of HTTP semantics over QUIC. This document also identifies HTTP/2 features that are subsumed by QUIC, and describes how HTTP/2 extensions can be ported to HTTP/3.
TLS Application-Layer Protocol Settings Extension
This document describes a Transport Layer Security (TLS) extension for negotiating application-layer protocol settings (ALPS) within the TLS handshake. Any application-layer protocol operating over TLS can use this mechanism to indicate its settings to the peer in parallel with the TLS handshake completion.
Using TLS Application-Layer Protocol Settings (ALPS) in HTTP
This document describes the use of TLS Application-Level Protocol Settings (ALPS) in HTTP/2 and HTTP/3. Additionally, it defines a set of additional HTTP SETTINGS parameters that would normally be impractical without ALPS.
Make using static table and Huffman encoding in QPACK opt-in
Update the HPACK static table
draft-bishop-httpbis-extended-settings-00 comments
TLS 1.3 and TCP interactions
Add application parameters to QUIC handshake and use it for H3 SETTINGS (comment)
Binding settings into session tickets
When to send the SETTINGS frame
Send complete SETTINGS
Move SETTINGS into TLS Handshake
Acknowledgments
This document has benefited from contributions and suggestions from Victor
Vasiliev.