Subject: Application-Layer Protocol Settings

From: Victor Vasiliev <[email-masked]>
Date: Mon, 6 Jul 2020 15:12:45 -0400

Hello TLS and HTTP working groups,

(QUIC WG bcc'd as this has been discussed there before)

Currently, we use SETTINGS frames as an extensibility mechanism in HTTP/2
and HTTP/3.  The SETTINGS frame is sent at the very beginning of TLS
application data; this approach, while simple, has some drawbacks.  The
most notable one is that when SETTINGS are used to negotiate extensions,
there is an entire round-trip where the client can send requests, but
doesn't know yet about any server extensions, thus making any
extension-dependant requests take an extra RTT.

The proposed solution to this problem is to move HTTP SETTINGS frame into
the TLS handshake.  Here are some issues where this has been discussed
before:

   - https://github.com/quicwg/base-drafts/issues/3086
   - https://github.com/quicwg/base-drafts/issues/3622
   - https://github.com/WICG/client-hints-infrastructure/pull/30

I wrote up a draft for the TLS extension that would solve this problem:
https://tools.ietf.org/html/draft-vvv-tls-alps-00

I also wrote up a draft that explains how to use that extension with HTTP,
and defines some settings (the ones discussed here
<https://github.com/quicwg/base-drafts/issues/3622>) that would not be
possible without it: https://tools.ietf.org/html/draft-vvv-httpbis-alps-00

I would appreciate feedback on those drafts.

Thanks,
  Victor.

---

From: Ben Schwartz <[email-masked]>
Date: Mon, 6 Jul 2020 22:23:22 -0400

Thanks for this draft.  I believe this is an important problem for HTTP
extensibility, and I'm glad to see work on a solution.

It occurs to me that this solution requires pretty tight integration
between the TLS termination and the HTTP backend.  Some TLS load balancers
already support ALPN, but they would have to be extended to support ALPS,
and I would worry about the potential for skew between the TLS terminator's
claimed settings and the backend's actual settings.

The draft says
   1.  While the server is technically capable of sending configuration
       to the peer as soon as it sends its Finished message, most TLS
       implementations do not allow any application data to be sent
       until the Finished message is received from the client.

Fixing this might require a change to some TLS implementations, but the
change to implement ALPS also seems significant.

The proposed 0-RTT interaction also seems like it would create a
significant risk of skew when a load balancer is in use, if the backend
settings can change.  Deployments that can't guarantee uniform backends
would have to disable 0-RTT (an unfortunate sacrifice for a feature that
saves 1 RTT!).

For load balancers, or any other situation where TLS and HTTP are loosely
coupled, sending SETTINGS at 0.5-RTT would seem like a much simpler
solution.  I know the draft mentions a few cases where this doesn't work
well, but perhaps there's a middle ground of some sort.  For example:

* If supporting generic 0.5-RTT forwarding is hard, TLS server
implementations could offer a configuration to send an arbitrary fixed
buffer at 0.5-RTT (depending on ALPN).  No standards change is required.
* The application protocol (here HTTP) could indicate what state is
guaranteed to persist across session resumption.  Although the preserved
state here (SETTINGS) is ~static, in general this could include dynamic
session state too.  This would move the change to HTTP, instead of TLS.

On Mon, Jul 6, 2020 at 3:13 PM Victor Vasiliev <vasilvv=
[email-masked]> wrote:

> _______________________________________________
> TLS mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/tls
>

---

From: "Martin Thomson" <[email-masked]>
Date: Tue, 07 Jul 2020 15:09:50 +1000

Hi Victor,

For HTTP/2, this is essentially a noop, as endpoints are required to send SETTINGS immediately.  Whether these bytes appear before Finished or not only affects endpoints that aren't inclined to wait for SETTINGS.  This is somewhat complicated by the way that TLS 1.2 and TLS 1.3 differ, but if we assume TLS 1.3 here, any uncertainty is easily avoided.

The main justification here appears to be based on the lack of 0.5-RTT send capability at some servers.  I don't know how to assess whether the cost of greater integration with the TLS stack is preferable to fixing the 0.5-RTT send problem.

For HTTP/3, this has some incremental effect beyond that.  In effect, this deliberately introduces head-of-line blocking for settings.  You can already do that in HTTP/3 if you are not prepared to deal with settings being in an ambiguous state.  There's a little more determinism here in terms of where you look for the data that unblocks progress, but with retransmissions, this is not a difference worth worrying about.

What this head-of-line blocking might allow is the development of new extensions that are unable to deal with uncertainty regarding SETTINGS.  But isn't it also possible to address that problem by saying "if you implement extension X, then you MUST NOT send requests prior to receiving SETTINGS?"

In QUIC, we decided that having the server repeat its configuration after 0-RTT was preferable to remembering it.  This was after a non-trivial number of questions about that part of the specification.  You seem to have taken the opposite approach.  Is that deliberate?  If so, why?

On Tue, Jul 7, 2020, at 05:12, Victor Vasiliev wrote:
> Currently, we use SETTINGS frames as an extensibility mechanism in 
> HTTP/2 and HTTP/3. The SETTINGS frame is sent at the very beginning of 
> TLS application data; this approach, while simple, has some drawbacks. 
> The most notable one is that when SETTINGS are used to negotiate 
> extensions, there is an entire round-trip where the client can send 
> requests, but doesn't know yet about any server extensions, thus making 
> any extension-dependant requests take an extra RTT.
> 
> The proposed solution to this problem is to move HTTP SETTINGS frame 
> into the TLS handshake. Here are some issues where this has been 
> discussed before:
>  * https://github.com/quicwg/base-drafts/issues/3086
>  * https://github.com/quicwg/base-drafts/issues/3622
>  * https://github.com/WICG/client-hints-infrastructure/pull/30
> I also wrote up a draft that explains how to use that extension with 
> HTTP, and defines some settings (the ones discussed here 
> possible without it: 
> https://tools.ietf.org/html/draft-vvv-httpbis-alps-00
>

---

From: Ilari Liusvaara <[email-masked]>
Date: Tue, 7 Jul 2020 12:06:46 +0300

> the TLS handshake.  Here are some issues where this has been discussed

I note at least two people have proposed just fixing TLS stacks to allow
sending HTTP/2 SETTINGS in 0.5-RTT data. I used to have a server that
actually did that (only if there was no CertificateRequest, due to
interface limitations, this was not TLS library limitation).

Unfortunately, this is not quite interoperable. There are HTTP/2
clients out there that just puke (with unexpected_message TLS alert,
sent post-Finished) if one tries to send SETTINGS in 0.5-RTT data.

I do not know what clients are involved (IIRC, I have heard about
problems with at least Firefox and Chrome, versions unknown), but I
would presume some sort of MITM by some client software is involved.

That was quite painful to debug. Much nastier than e.g., debugging
handshakes failing with illegal_parameter due to downnegotiation gone
wrong due to server bug (this client is still using TLS 1.3 draft 23,
and is still out there).

-Ilari

---

From: David Benjamin <[email-masked]>
Date: Tue, 7 Jul 2020 15:11:20 -0400

Hi Martin,

You’re right that this is closely related to half-RTT data. However, I
don’t think this is a no-op for HTTP/2.

I’m not aware of HTTP/2 clients that wait for the SETTINGS frame today.
Doing so costs a round-trip with servers that don’t send SETTINGS in
half-RTT, and there's no indicator for whether the server will send it.
I’ll see about testing some sites here and will report back, but I expect
most do not. We (correctly) designed TLS 1.3 as a drop-in replacement for
TLS 1.2, which means that we don't get to key new I/O patterns on it.
Half-RTT data is a very weird state and wouldn’t get used by default. This
is the problem with “no standards change is required” style of thinking
around simply changing I/O patterns. A protocol is more than its wire
image. Changing the I/O patterns is a protocol change.

This means we cannot get efficient and reliable feature negotiation today.
Moreover, HTTP/2 servers today may send ServerHello..Finished without
application data in their first flight, so we need *some* change to the TLS
flight, be it ALPS or just some indicator.

Let’s look at what it’d take to make half-RTT SETTINGS work. We need some
“I will send half-RTT data, so you can safely wait for it” indicator. Then
the client needs to know when it is done waiting. We could say it’s one
SETTINGS frame, but that only allows integer values. (Related:
EXTENDED_SETTINGS
<https://tools.ietf.org/id/draft-bishop-httpbis-extended-settings-01.html>
and discussion
<https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0127.html>.)
Those currently need separate frames, and one cannot wait for the absence
of a frame. Maybe we need an HTTP-level
SETTINGS_WILL_SEND_HALF_RTT_XYZ_FRAME indicator to keep the delimiter in
HTTP, or a TLS-level “end of half-RTT data” delimiter. (Now consider how
that works in QUIC...)

Next we need to tackle 0-RTT. Waiting for half-RTT data costs a round-trip
in 0-RTT, so we need something to persist across the session, with
semantics around mismatch and whatnot. (Another TLS-visible change.)
Anything persisted in the session must have bounded size, and be delivered
in something ordered with NewSessionTicket.

If we place those bytes inside the handshake, we’ve reinvented ALPS. If we
place them outside, the NewSessionTicket ordering becomes complex,
especially in QUIC
<https://github.com/quicwg/base-drafts/issues/2945#issuecomment-519338186>.
To your question about the server repeating its configuration vs. the
client remembering it, I believe the issue was exactly that ordering
mishap. ALPS avoids this because EncryptedExtensions and NewSessionTicket
are ordered.

On top of this, the half-RTT point in a non-0-RTT connection is a weird
state. Not all connection properties (e.g. client certs) have been
established yet, and writes out of turn are tricky. This message
<https://mailarchive.ietf.org/arch/msg/tls/hymweZ66b2C8nnYyXF8cwj7qopc/>
discusses
some of the challenges here. I would argue something like ALPS is the
settings design we should have had all along.

David

On Tue, Jul 7, 2020 at 1:10 AM Martin Thomson <[email-masked]> wrote:

> Hi Victor,
>
> For HTTP/2, this is essentially a noop, as endpoints are required to send
> SETTINGS immediately.  Whether these bytes appear before Finished or not
> only affects endpoints that aren't inclined to wait for SETTINGS.  This is
> somewhat complicated by the way that TLS 1.2 and TLS 1.3 differ, but if we
> assume TLS 1.3 here, any uncertainty is easily avoided.
>
> The main justification here appears to be based on the lack of 0.5-RTT
> send capability at some servers.  I don't know how to assess whether the
> cost of greater integration with the TLS stack is preferable to fixing the
> 0.5-RTT send problem.
>
> For HTTP/3, this has some incremental effect beyond that.  In effect, this
> deliberately introduces head-of-line blocking for settings.  You can
> already do that in HTTP/3 if you are not prepared to deal with settings
> being in an ambiguous state.  There's a little more determinism here in
> terms of where you look for the data that unblocks progress, but with
> retransmissions, this is not a difference worth worrying about.
>
> What this head-of-line blocking might allow is the development of new
> extensions that are unable to deal with uncertainty regarding SETTINGS.
> But isn't it also possible to address that problem by saying "if you
> implement extension X, then you MUST NOT send requests prior to receiving
> SETTINGS?"
>
> In QUIC, we decided that having the server repeat its configuration after
> 0-RTT was preferable to remembering it.  This was after a non-trivial
> number of questions about that part of the specification.  You seem to have
> taken the opposite approach.  Is that deliberate?  If so, why?
>

---

From: David Benjamin <[email-masked]>
Date: Tue, 7 Jul 2020 15:14:14 -0400

Hi Ben,

(I’ve covered many of these points in my reply to Martin, so you may want
to read that first.)

Any solution here involves a TLS change, even for servers which currently
send half-RTT settings. See my reply to Martin for why. The question then
is which is more complex. As a TLS implementor, ALPS would be a very
straightforward extension to implement, while the work involved to make
half-RTT SETTINGS work would be a mess.

Transparently sending a fixed buffer of half-RTT data was indeed something
we’d thought about and rejected. In some circumstances, it may cause
deadlocks with TCP
<https://mailarchive.ietf.org/arch/msg/tls/hymweZ66b2C8nnYyXF8cwj7qopc/>.
And we still need an indicator for the client to safely wait for it. I/O
patterns are part of the protocol.

It’s also not the case that non-uniform backends must disable 0-RTT. That
is what 0-RTT rejection logic is for. Non-uniform deployments may get less
0-RTT than a uniform deployment, but it won’t break things. This is already
the case (ALPN must match) and unavoidable with any predictive mechanism
like 0-RTT.

Finally, you’re right to think about the coupling between TLS and HTTP for
0-RTT, but I believe you have the conclusion backwards. The TLS stack must
be deeply aware of what is stored in the TLS session, so the server can
reject 0-RTT when the remembered values are incompatible with its current
configuration (see HTTP/3
<https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-7.2.4.2-7>).
Otherwise the client will act thinking the server supports some extension
when, in reality, it does not. (Perhaps the server had to roll the feature
back.)

The simpler that TLS/HTTP interaction, the looser the coupling we can
manage, and checking opaque bytes for equality is the simplest possible
option here. Tighter coupling could be aware that, e.g.,
SETTINGS_MAX_CONCURRENT_STREAMS = 500 is compatible with 1000 but not 100.
The draft starts with the simplest option, given settings don’t change
much. It’s already the case that configuration changes, like cipher
preferences, may reject 0-RTT. (Note settings which do change can still be
sent in application data. ALPS’s purpose is to solve the reliable
negotiation problem, and any changing setting won’t be reliable in 0-RTT
anyway. Moving them out of ALPS entirely seems fairly clean.)

David

On Mon, Jul 6, 2020 at 10:23 PM Ben Schwartz <bemasc=
[email-masked]> wrote:

> settings can change..  Deployments that can't guarantee uniform backends
>>    <https://github..com/quicwg/base-drafts/issues/3086>

---

From: Ben Schwartz <[email-masked]>
Date: Tue, 7 Jul 2020 16:37:57 -0400

On Tue, Jul 7, 2020 at 3:14 PM David Benjamin <[email-masked]> wrote:

> send half-RTT settings. ...
>

I think a new ALPN protocol ID
("h2-but-with-settings-from-the-server-asap-for-real") would suffice.

> is what 0-RTT rejection logic is for. ...
>

I would be impressed if there is any TLS load balancer architecture that
supports 0-RTT rejection by the backend.  This would require an interesting
new metadata layer, quite different from the usual "decrypt and forward"
approach.  (Of course, I assume that most load balancers simply won't
implement 0-RTT at all.)

> option here.

I'm not sure what equality check you're proposing; I don't see it in the
draft.  However, I agree with your conclusion: if the TLS server manages
the settings-state, it can easily invalidate resumption across a settings
change.

Ultimately, I think I'm saying something obvious: if the TLS server
represents multiple backends without distinction, it can't represent a
property that those backends do not share.  This is true of ALPN, and would
be true of ALPS too.  This is fine; the ALPS just has to represent the
intersection of backend capabilities.  All currently defined HTTP/2
Settings appear to support intersection in a reasonable way, although I'm
not sure this is guaranteed in general.  However, SETTINGS at 0.5-RTT would
not have this problem; heterogeneous backends could each report their own
SETTINGS.

This is not an unreasonable design choice given the other constraints
you've mentioned, but it is a limitation, and potentially a footgun (e.g.
if someone forgets to revert the ALPS config change before rolling back the
HTTP server config change).

---

From: David Benjamin <[email-masked]>
Date: Tue, 7 Jul 2020 17:17:14 -0400

> ("h2-but-with-settings-from-the-server-asap-for-real") would suffice.

That doesn't suffice. Please see my reply to Martin. This would be one
possible spelling of the indicator, but it would not provide the other
components necessary for half-RTT data to work.

> approach.  (Of course, I assume that most load balancers simply won't

HTTP/3 0-RTT *already* requires such an interaction. In fact, it requires
an even more complex version than ALPS. The link was lost in the quoted
reply, so I'll include it again:
https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-7.2.4.2-7

This is fundamentally unavoidable if you want 0-RTT to be able to use
negotiated parameters. Any negotiated parameter available to 0-RTT *must* be
available predictively. Because it is predictive, mispredictions may occur.

RFC8470 likewise contains recommendations which also require more than a
"decrypt and forward" approach.

> draft.

It's right here: https://tools.ietf.org/html/draft-vvv-tls-alps-00#section-3

>   For application protocols that support 0-RTT data, both the client
>   and the server have to remember the settings provided by the both
>   sides during the original connection.  If the client sends 0-RTT data
>   and the server accepts it, the ALPS values SHALL be the same values
>   as were during the original connection.  In all other cases
>   (including session resumption that does not result in server
>   accepting early data), new ALPS values SHALL be negotiated.
>
>   If the client wishes to send different client settings for the 0-RTT
>   session, it MUST NOT offer 0-RTT.  Conversely, if the server would
>   send different server settings, it MUST reject 0-RTT.  Note that the
>   ALPN itself is similarly required to match the one in the original
>   connection, thus the settings only need to be remembered or checked
>   for a single application protocol.

> However, I agree with your conclusion: if the TLS server manages the
> settings-state, it can easily invalidate resumption across a settings
> change.
>

I don't think this follows. ALPS and half-RTT data happen at the same
round-trip. If the frontend is able to forward half-RTT data, it has
clearly decided on which backend to use by the time it's assembling the
ServerHello flight. It can as easily pick a backend-specific ALPS value as
it can pick backend-specific half-RTT data.

Beyond that, it's a question of what exactly your frontend/backend split
looks like. I gather you're worried about a deployment scenario where your
frontend is a TLS terminator, which has a boring pipe to the HTTP backend,
without any out-of-band signaling. (As opposed to having an HTTP frontend.)
In that case, the argument is that, since half-RTT data is just bytes, that
can be transparently forwarded over the pipe, whereas an ALPS signal
wouldn't. Is that right?

It's unlikely half-RTT data would work for that scenario. The frontend most
likely waits for the handshake to actually finish, before enabling the
pipe. Indeed, the security properties of the half-RTT point are kind of
subtle (particularly with client certs). Forwarding data then without
appropriate signaling is dangerous.

Such a frontend/backend split would also likely be unable to manage the
recommendations in RFC8470, the remembered settings vs. 0-RTT interactions,
the guarantee of half-RTT data being sent early enough, or the delimiting
information necessary to make a half-RTT settings work. For that matter, it
already needs some out-of-band signaling to communicate the ALPN protocol.

ALPS probably even helps this kind of deployment, by at least making it
possible to statically configure the settings. Static configuration risks
the footguns you mention below, but when all you've got is a boring pipe,
there aren't many options.

> HTTP server config change).

Again, this depends on where your frontend/backend split is, and what is
the communication between them. Note also that this hypothetical deployment
model already has a similar footgun around ALPN.

David

---

From: "Martin Thomson" <[email-masked]>
Date: Wed, 08 Jul 2020 11:28:13 +1000

Hi David,

I think that there is an important difference between something that is hard to realize in practice (as many aspects of this clearly are) and using that to say that the fundamental protocol definition is wrong.

I appreciate - at least superficially - the complexities involved here.  Having implemented them, and having worked around many of the problems you have identified, it was not trivial to implement 0-RTT or 0.5-RTT (the latter was pretty-much trivial for much the same reason that false start works, but I'll concede that I probably didn't fully explore all of the potential problems).

But as much as recognizing implementation complexity is important, that doesn't necessarily translate into a requirement to change the protocol.

Let's take an example of a feature you are trying to negotiate in HTTP (/2 or /3).  I don't think that it is unreasonable to say to a client that it cannot attempt anything that depends on this feature until it receives SETTINGS.  You can then require servers that support this extension to send SETTINGS in 0.5-RTT so that the client is only blocked on the extra bytes and not additional round trips.  All of which implies that you need TLS 1.3 for the feature.

The drawback there is that the client that wants to use the feature might not receive the SETTINGS in time and they don't get a clear indication that this is not happening.  Ben's suggestion to use a new version if you care about avoiding that case is entirely appropriate.  It depends on what sort of extensions are being contemplated here to determine whether this is indeed necessary.  I tend to think a h2_tls13 ALPN that mandated use of 0.5-RTT for SETTINGS would put a big dent in this negotiation problem.

Either way, your stack might require new changes to support the writing of some fixed amount of data on all new connections.  This might turn into a requirement on TLS terminators to have per-backend configuration to support this new information.  But these don't necessarily turn into new protocol mechanisms.  Indeed, these changes are far less disruptive overall than a completely new TLS extension, particularly if the TLS extension involves all of the same coordination.

I concede that saying that SETTINGS is sufficient isn't free, and that there is some additional cost on implementations.  On the other hand, the "cost" is that implementations improve some aspects of an existing protocol that provide other benefits to those implementations.

On the other hand, new mechanisms like this require the same amount of coordination, more work at the TLS layer, and all the delays imposed by standardization.

On Wed, Jul 8, 2020, at 05:11, David Benjamin wrote:
> I’ll see about testing some sites here and will report back, but I 
> expect most do not. We (correctly) designed TLS 1.3 as a drop-in 
> replacement for TLS 1.2, which means that we don't get to key new I/O 
> patterns on it. Half-RTT data is a very weird state and wouldn’t get 
> used by default. This is the problem with “no standards change is 
> required” style of thinking around simply changing I/O patterns. A 
> protocol is more than its wire image. Changing the I/O patterns is a 
> protocol change.
> 
> This means we cannot get efficient and reliable feature negotiation 
> today. Moreover, HTTP/2 servers today may send ServerHello..Finished 
> without application data in their first flight, so we need *some* 
> change to the TLS flight, be it ALPS or just some indicator.
> 
> Let’s look at what it’d take to make half-RTT SETTINGS work. We need 
> some “I will send half-RTT data, so you can safely wait for it” 
> indicator. Then the client needs to know when it is done waiting. We 
> could say it’s one SETTINGS frame, but that only allows integer values. 
> (Related: EXTENDED_SETTINGS 
> <https://tools.ietf.org/id/draft-bishop-httpbis-extended-settings-01.html> and discussion <https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0127.html>.) Those currently need separate frames, and one cannot wait for the absence of a frame. Maybe we need an HTTP-level SETTINGS_WILL_SEND_HALF_RTT_XYZ_FRAME indicator to keep the delimiter in HTTP, or a TLS-level “end of half-RTT data” delimiter. (Now consider how that works in QUIC...)
> 
> Next we need to tackle 0-RTT. Waiting for half-RTT data costs a 
> round-trip in 0-RTT, so we need something to persist across the 
> session, with semantics around mismatch and whatnot. (Another 
> TLS-visible change.) Anything persisted in the session must have 
> bounded size, and be delivered in something ordered with 
> NewSessionTicket.
> 
> If we place those bytes inside the handshake, we’ve reinvented ALPS. If 
> we place them outside, the NewSessionTicket ordering becomes complex, 
> especially in QUIC 
> <https://github.com/quicwg/base-drafts/issues/2945#issuecomment-519338186>. To your question about the server repeating its configuration vs. the client remembering it, I believe the issue was exactly that ordering mishap. ALPS avoids this because EncryptedExtensions and NewSessionTicket are ordered.
> 
> <https://mailarchive.ietf.org/arch/msg/tls/hymweZ66b2C8nnYyXF8cwj7qopc/> discusses some of the challenges here. I would argue something like ALPS is the settings design we should have had all along.
> 
> David
>

---

From: Victor Vasiliev <[email-masked]>
Date: Wed, 8 Jul 2020 10:13:33 -0400

> cost of greater integration with the TLS stack is preferable to fixing the

It's both about solving the "lack of 0.5-RTT send capability" problem, and
about making the client aware that it will in fact get the settings in
0.5-RTT without having to risk waiting for an entire RTT.  I don't think
you can avoid putting a "I will correctly send and receive 0.5-RTT data"
signal into any location other than the TLS handshake, so this is less of a
question of *should*, and more of *how*.

For what it's worth, I don't think we should define a new ALPN token for
that; using ALPN tokens for flags will eventually lead to combinatorial
explosion (e.g. "if we define h2_half_rtt, we have to define h2c_half_rtt",
etc), and can also lead to some really unpleasant situations with Alt-Svc.

Also, as far as I am aware, SETTINGS are currently not carried over for
HTTP/2 0-RTT in any form, meaning that it's currently impossible to, for
example, send a WebSocket CONNECT request in HTTP/2 0-RTT.  The proposed
draft fixes that.

> implement extension X, then you MUST NOT send requests prior to receiving

This probably works for 1-RTT, but I am not quite sure it would work with
0-RTT as currently defined in HTTP/3.

> taken the opposite approach.  Is that deliberate?  If so, why?

HTTP/3 approach to 0-RTT settings is based around the idea that things work
just fine with default settings (which is true if you don't have extensions
you care about), whereas ALPS aims to provide "actual settings are always
there" guarantee.  If you define extensions that require blocking on
settings, then not remembering settings makes 0-RTT useless anyways, so
this is kind of moot.  That said, we could add an "upgrade to compatible
settings" mechanism similar to QUIC if people believe it's useful.

Also, from what I recall, the approach we chose for HTTP/3 was partially
motivated by the ordering ambiguity between SETTINGS and NewSessionTicket,
which the proposed draft removes.

---

From: "Martin Thomson" <[email-masked]>
Date: Thu, 09 Jul 2020 10:16:24 +1000

On Thu, Jul 9, 2020, at 00:13, Victor Vasiliev wrote:
> For what it's worth, I don't think we should define a new ALPN token 
> for that; using ALPN tokens for flags will eventually lead to 
> combinatorial explosion (e.g. "if we define h2_half_rtt, we have to 
> define h2c_half_rtt", etc), and can also lead to some really unpleasant 
> situations with Alt-Svc.

I'm not so firm on that.  h2 was defined before 0-RTT, so there is no provision for carrying settings over into 0-RTT anyway, which is what would be required for thewebsocketprotocol CONNECT to work.  You propose defining extensions to TLS to address this shortcoming in addition to the synchronization issue, but what that really is is a new version of h2 - one where SETTINGS does not appear in application data (mostly, I assume that updates are OK).

This was discussed during the design of HTTP/2.  But 0-RTT was too new to decide anything at that point and the view was that anything could be negotiated in one of two ways: SETTINGS (which takes time) or a new protocol version.  It might seem a little early to be even contemplating a new version, but that wasn't the thinking at the time.

h2c is dead, so we don't need to worry about that.

---

From: Lucas Pardue <[email-masked]>
Date: Mon, 20 Jul 2020 20:10:19 +0100

Hi Victor,

It seems my brain skipped over "ALPS in HTTPS" [1] when you mentioned in
your original email. I was reading it in the context of David Benjamin's
thread on Client Hint Reliability [2]. There's a couple of things that
surprised me when reading both drafts:

1. ALPS in HTTPS actually supports more than just exchanging Settings
Parameters, it can actually hold a series of frames. It's just that ALPS
only defines SETTINGS to be allowed, and Client Hints Reliability wants to
add more in the shape of a new ACCEPT_CH frame. I'm not sure I like the
idea of supporting any old frame in the TLS handshake, SETTINGS are at
least reasoned about in terms of how they are remembered for the purposes
of 0-RTT.
2. ALPS in HTTPS makes it mandatory to support some settings to disable
static and Huffman header compression. That seems pretty onerous. If there
was interest in prototyping something like ACCEPT_CH-in-handhsake it
requires a modification of a QPACK dependency. On the other hand, if you
don't make these settings mandatory, then you won't achieve your objective
of removing the mandatory parts of HPACK/QPACK. To me this is a signal that
ALPN is a better option to negotiate a profile of H2/H3 that modifies
mandatory compression behaviour.

Cheers
Lucas

[1] https://tools.ietf.org/html/draft-vvv-httpbis-alps-00
[2] https://lists.w3.org/Archives/Public/ietf-http-wg/2020JulSep/0054.html

---

From: Victor Vasiliev <[email-masked]>
Date: Mon, 20 Jul 2020 15:33:21 -0400

> least reasoned about in terms of how they are remembered for the purposes

It explicitly bans all existing frames that are not SETTINGS.  The problem
here is that SETTINGS only supports integral values, so we'd be limited to
those if we make ALPS just SETTINGS.

> mandatory compression behaviour.

That's a fair point.  I think I have an idea of how to split those settings
into a separate draft without resorting to a new ALPN token.

---

From: David Benjamin <[email-masked]>
Date: Mon, 20 Jul 2020 16:38:34 -0400

> those if we make ALPS just SETTINGS.

Right, concretely there is an "Allowed in ALPS" column added by Victor's
ALPS document, which my document sets for the new frame. Old frames weren't
designed with ALPS in mind, so the ALPS document needs to make a decision.
New frames can reason about the implications of opting into ALPS and do so.

As Victor notes, it's only a new frame because we got SETTINGS values wrong
and, per earlier discussion, the extension point we currently have is new
frames. If we want something even more restrictive, we could instead
revive draft-bishop-httpbis-extended-settings, say only SETTINGS and
EXTENDED_SETTINGS are allowed, and close it there. But I think the new
column works fine and matches how this sort of thing usually works.

> That's a fair point.  I think I have an idea of how to split those
> settings into a separate draft without resorting to a new ALPN token.
>
>
>>
>> Cheers
>> Lucas
>>
>>
>> [2]
>> https://lists.w3.org/Archives/Public/ietf-http-wg/2020JulSep/0054.html
>>

---

From: Lucas Pardue <[email-masked]>
Date: Mon, 20 Jul 2020 22:00:48 +0100

On Mon, 20 Jul 2020, 21:38 David Benjamin, <[email-masked]> wrote:

>> It explicitly bans all existing frames that are not SETTINGS.  The
>> problem here is that SETTINGS only supports integral values, so we'd be
>> limited to those if we make ALPS just SETTINGS.
>>
>
> As Victor notes, it's only a new frame because we got SETTINGS values
> wrong and, per earlier discussion, the extension point we currently have is
> new frames. If we want something even more restrictive, we could instead

That makes sense but I guess I don't see the point in defining a new thing
that contains frames that are never sent on streams. That is, if these are
connection settings, just send the payload. Unframed extended settings
might get you there, if you can find a way to encapsulate conventional
settings inside them, then all the better.

Cheers
Lucas

/tls <https://www.ietf.org/mailman/listinfo/tls>

---

From: David Benjamin <[email-masked]>
Date: Mon, 20 Jul 2020 17:42:15 -0400

On Mon, Jul 20, 2020 at 5:00 PM Lucas Pardue <[email-masked]>
wrote:

>>>> It seems my brain skipped over "ALPS in HTTPS" [1] when you mentioned
>>>> in your original email. I was reading it in the context of David Benjamin's

Could you elaborate on this a bit? I'm probably just failing to parse, but
I'm not sure which alternative you're suggesting here. (Ah, the wonders of
email.)

David

---

From: Lucas Pardue <[email-masked]>
Date: Tue, 21 Jul 2020 13:22:02 +0100

On Mon, Jul 20, 2020 at 10:42 PM David Benjamin <[email-masked]>
wrote:

>> That makes sense but I guess I don't see the point in defining a new
>> thing that contains frames that are never sent on streams. That is, if
>> these are connection settings, just send the payload. Unframed extended
>> settings might get you there, if you can find a way to encapsulate
>> conventional settings inside them, then all the better.
>>
>

I was trying to accommodate HTTP/2 and HTTP/3 in one breath, which is why
my intent was probably unclear. Basically, if ALPS relies on frames for
per-protocol settings then it has to accommodate the differences in frame
format between HTTP/2 and HTTP/3. In the examples from the ALPS and Client
Reliability proposals, the H2 frame needs to populate the frame header and
it pick stream 0, which doesn't exist until the connection is actually
made, so seems a bit kludgy. In H3, frames don't have the stream ID so you
avoid the problem above.

So my thought was to basically do away with the notion of protocol-specific
frames in ALPS, and instead define the a common payload format that perhaps
looks something like bishop-extended-settings [1], a series of
Type-Length-Value (but without any frame headers). This would allow you to
encode the old and new settings in a single format, rather than needing to
delineate things via frames.

[1] -
https://tools.ietf.org/html/draft-bishop-httpbis-extended-settings-01#section-3.1.1

---

From: David Benjamin <[email-masked]>
Date: Tue, 21 Jul 2020 11:48:55 -0400

On Tue, Jul 21, 2020 at 8:22 AM Lucas Pardue <[email-masked]>
wrote:

>> Could you elaborate on this a bit? I'm probably just failing to parse,
>> but I'm not sure which alternative you're suggesting here. (Ah, the wonders
>> of email.)
>>
>> David
>>
>
> So my thought was to basically do away with the notion of
> protocol-specific frames in ALPS, and instead define the a common payload
> format that perhaps looks something like bishop-extended-settings [1], a
> series of Type-Length-Value (but without any frame headers). This would
> allow you to encode the old and new settings in a single format, rather
> than needing to delineate things via frames.
>
> [1] -

Ah, gotcha. The thinking was the settings were ALPN-specific anyway, so we
may as well define them however is more idiomatic for the protocol. This
means we automatically can make existing H2 and H3 settings more reliable.
Settings values can also be updated over the course of the connection, so
using frames keeps continuity there. But, yeah, a separate key/value syntax
would work too.

(A small correction, the current Client Hint Reliability proposal allows
ACCEPT_CH to be sent in application data too. Maybe the frontend realizes
the origin's ACCEPT_CH preferences have changed and wants to notify
existing connections. Though I don't consider this feature important. I
doubt most folks, if anyone, will bother with this. Mostly that's how a
SETTINGS or EXTENDED_SETTINGS value already would have worked, so I figured
the semantics ought to be compatible in case EXTENDED_SETTINGS is revived.)

David

---

From: Victor Vasiliev <[email-masked]>
Date: Tue, 21 Jul 2020 16:22:30 -0400

How would this work with regular SETTINGS?  HTTP/2 and HTTP/3 have disjoint
setting number spaces, and it's unclear to me whether there's any
significant overlap between those.

On Tue, Jul 21, 2020 at 11:49 AM David Benjamin <[email-masked]>
wrote:

>>> On Mon, Jul 20, 2020 at 5:00 PM Lucas Pardue <
>>> [email-masked] <[email-masked]>> wrote:
>>>
>>>>

---

From: David Benjamin <[email-masked]>
Date: Tue, 21 Jul 2020 16:59:29 -0400

I guess you could have protocol-specific numbers and protocol-independent
syntax? Or you could allocate numbers in yet another number space for all
the existing settings. The latter seems like a lot of fuss, and the former
is kinda weird. At that point you may as well get a protocol-specific blob
(as in the draft) so the protocol library can reuse their preferred parsing
routines.

On Tue, Jul 21, 2020 at 4:22 PM Victor Vasiliev <[email-masked]> wrote:

> How would this work with regular SETTINGS?  HTTP/2 and HTTP/3 have
> disjoint setting number spaces, and it's unclear to me whether there's any
>>> I was trying to accommodate HTTP/2 and HTTP/3 in one breath, which is
>>> why my intent was probably unclear. Basically, if ALPS relies on frames for
>> Ah, gotcha. The thinking was the settings were ALPN-specific anyway, so
>> we may as well define them however is more idiomatic for the protocol. This

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 22 Jul 2020 00:43:46 +0100

As I understood things in ALPS, each application protocol has its own
settings so I don't see there being too much problem with the disjoint
number spaces. It is a bit fussy but it avoids having to rework existing
stacks to parse frames that don't belong to any streams.  From the stacks
that I'm experienced with, frame parsing and stream state are wrapped
tightly. Unless you mean that you expect an endpoint to use parsing
primitives to parse a frame, which seems like it would duplicate things.
Instead just having unframed settings that carry properties of a
yet-to-be-fully-instantiated endpoint connection seems something to have
less impact. But of course YMMV.

Cheers
Lucas