Hi,

On Fri, Jun 5, 2015 at 6:11 AM, Xuelei Fan <xuelei....@oracle.com> wrote:
> I think it should be true that if a server can negotiate h2, the server
> MUST support H2 and the enabled cipher suites MUST contains at least one
> H2 required cipher suite.  Otherwise, it's bug in server side.
>
> It's instinctive that if a server support h2, and then the application
> protocol selector would select h2.  If the server declare to support h2,
> but no suitable cipher suites, it may be a server bug.  The connection
> should be terminated rather than downgrade to HTTP/1.1, I think.

The server may support h2, but there is no valid h2 cipher in common
with the client, so it's not a server bug.
In that case, client and server cannot speak h2, but nothing forbids
them to speak http/1.1.
It would be really bad for the user experience if both client and
server could speak http/1.1, but they don't just because they can't
speak h2.
They would appear like spoiled children :)

The point of ALPN is to *negotiate* a protocol, not to give up on the
first failure.

> Is it possible that client only request h2_valid_cipher_a, but server
> only support h2_valid_cipher_b, and as would result in that there is no
> common cipher suites between client and server for H2?  It is possible,
> surely.  Should the connection be terminated, or fall-back to HTTP/1.1?
>  I think connection should be terminated immediately, rather than
> fall-back to HTTP/1.1.  Per page 68, section 9.2.2, RFC 7540, there is
> an mandatory cipher suite (TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) MUST
> be supported in both client and server.  If there is no common cipher
> suites between client and server for H2, it is actually a bad
> deployments, and the connection should be terminated rather than
> fall-back to HTTP/1.1.  Version downgrading is not a safe behavior, I think.

That is not what the 7540 expert group thinks, certainly not what
browsers do, and certainly not what servers do.
The behavior is to speak http/1.1 (or the next protocol that fits).

> That's an interesting case.  The question actually is: between requested
> application protocols and cipher suites, which preference should be
> respected at first.  Because it is a application requirement that a
> certain cipher suite is not suitable to H2, I think requested
> application protocols should be respected at first.
>
> My scenarios look like:
> 1. client sends [h2_invalid_cipher, h2_valid_cipher] and h2/http/1.1
> application protocol.
> 2. server selects h2 (we need an API for the selection).
> 3. server selects h2_valid_cipher because of h2 is selected previously
> (may need an API for the selection).

Does not work. How do you know that server has h2_valid_cipher available ?
If it does not, you have picked h2, and an invalid cipher (breaks
7540), or you terminate the connection while instead you could speak
http/1.1.

> In #1, if there is no h2_valid_cipher requested, it is a bug in client side.
> In #3, if there is no h2_valid_cipher that can be negotiated, it is a
> bug in server side, or the client does not enabled the mandatory cipher
> suite (a bug in client).

Does not work.
The client may be using TLS 1.4, where that mandatory cipher suite
(it's mandatory only for TLS 1.2 deployments) has been removed because
insecure.
There is no bug on either side, just no cipher in common.

> I still cannot understand the outcome.  I think, if there is no h2 valid
> cipher in common, the connection should be terminated as there is a bug
> in client or server side (see above).

No, see above.

> I'm not familiar with HTTP/2 protocol, can you share more scenarios that
> application protocol selection depends on the cipher?

It is evident.

In all examples, yours and mines, every time we pick "h2" we have to
look at the ciphers to see if it is a valid one for h2 or not.
You cannot pick "h2" without looking at the cipher so there is an
evident dependency.
If it's not the right cipher, you say "close the connection", while
the implemented behavior of browsers and servers is to fallback to
http/1.1.
Either case, you have looked at the cipher and taken a decision based
on the tuple (app_proto, cipher).

In contrast, you can pick "http/1.1" and *any* cipher you want, you
don't need to look at the cipher.

>> A bit of warning here: we are designing an API for ALPN, not for HTTP/2.
>> The ALPN API should be flexible enough to implement *at least* HTTP/2,
>> possibly even more complex scenarios (for example alias selection),
>> but IMHO it should not be tied to HTTP/2.
>>
> Yes.  That's what I intended to do now.  It's very bad if application
> protocol selection depends on the negotiation of TLS protocols, cipher
> suites, or other handshake attributes, or other Chicken/Eggs dependence.
> As would make the JSSE provider hard to be implemented, and the API hard
> to be used.  That's what I want to avoid in JSSE layer.
>
>> Again, I see 2 cases: either the JDK implementation picks the TLS
>> protocol, the cipher and the alias like it does now, and then invokes
>> the "callback" to pick the application protocol (current Jetty ALPN
>> behavior), or the implementation must be reviewed to perform TLS
>> protocol, cipher, alias and application protocol selection at once,
>> with a "callback" that will be invoked possibly multiple times until
>> it can find the right tuple to return.
>>
> The former has a drawback that the cipher may not suitable for the
> application protocol.  It's application protocol define with cipher
> suite is suitable (RFC7540), not cipher suite define which application
> protocol is suitable.  So application protocol should be selected at
> first, and let the specific application protocol determines the
> negotiable cipher suite.

That forbids any form of fallback to http/1.1, and it's not what it's
intended by 7540, nor what has been implemented by browsers and
servers.

IMHO would be very bad to kill the whole communication between a
client and a server just because they can't speak h2.
The whole world speaks http/1.1 no problem, so why now they could not anymore ?
I understand h2 is preferred, but that should not stop a browser and a
server to use http/1.1 if they can't use h2.

> The latter made the TLS implementation pretty complicated.  It is even
> not doable actually in general. Too much attributes need to be
> considered if more handshake properties are involved, such as
> certificate, key parameters, etc.

I am not sure about the impossibility.
IIUC, there are 4 parameters that needs to be negotiated: TLS
protocol, cipher, alias and application protocol.
The data in the ClientHello and the server configuration certainly
allow for such a tuple to be generated, so it's not impossible.
Sure, it may be really hard on the implementation.

The current Jetty ALPN support has taken the shortcut that application
protocol is negotiated after cipher selection.
Sure, Jetty ALPN can't pick the protocol based on the alias for example.
And it has to sort the ciphers in a HTTP/2 specific way to influence
cipher selection to prefer those that would be good for HTTP/2.
It's not perfect but works.

> See also my previous mail about the rerouting requirement.

Which I am not sure I understand.
If the router decides the application protocol, it must have the
correct logic, and the server can't choose anything.
If the router routes to a server thinking that it would speak h2, but
then the server does not negotiate h2, that means the router has no
power in deciding anything.
I am sure I am missing something from your example ?

We have deployed a rerouting using HAProxy and Jetty in our own
website a while back, using spdy (that has no cipher requirements).
If spdy was negotiated we routed the traffic to one connector,
otherwise to another connector.
However, HAProxy was offloading TLS and was speaking clear text to the
backend servers.

Is that your scenario ?

> I think application-layer protocol negotiation should happen before the
> actually general-handshaking (TLS protocol, cipher suite, general
> extension negotiation).  For any incoming ClientHello message, the
> scenarios in server side is as simple as:
> 1. select the right application-layer protocols.
> 2. do the actual general handshaking.  If something failed, terminate
> the connection.

Nope.

Imagine a server that overnight added h2 support.

Yesterday a browser could open a page and browse the site over http/1.1.
Today, the browser cannot even connect to the website (because you
don't allow fallback).
But if you use Netscape 4, you can actually connect and browse the
site as before :)

Imagine how much the adoption of h2 would be popular if that was the case.
Certainly the 7540 expert group did not want this.

> I'm not familiar with HTTP/2, I'm open to hear more case why above
> scenarios does not work.

See above.

Thanks !

-- 
Simone Bordet
http://bordet.blogspot.com
---
Finally, no matter how good the architecture and design are,
to deliver bug-free software with optimal performance and reliability,
the implementation technique must be flawless.   Victoria Livschitz

Reply via email to