Subject: [hybi] Modest enhancement to XOR-based masking

From: Eric Rescorla <[email-masked]>
Date: Sat, 29 Jan 2011 06:54:11 -0800

Maciej has suggested that an XOR-based masking mechanism enables
"canned" messages
using non-WS clients (e.g., the FORM tag) to be sent to a WS server
and accepted.

In private, Adam suggested an easy fix for this: the per-packet mask
is a combination of a
server-provided per-connection mask and a client-provided per-packet mask.

I.e.,

1. During the handshake the server provides M1.
2. For each packet P the client generates M2 and sends:

M2    ||      P[i] ^ M1[i %M1.len] ^ M2[i ^% M2.len]

This has at most a modest performance cost over the existing repeating
mask and has the
impact of randomizing canned messages from the server perspective,
thus removing the
possibility of that mechanism.

Thoughts?

-Ekr

---

From: Willy Tarreau <[email-masked]>
Date: Sat, 29 Jan 2011 16:11:33 +0100

Hello Eric,

On Sat, Jan 29, 2011 at 06:54:11AM -0800, Eric Rescorla wrote:
> mask and has the impact of randomizing canned messages from the server
> perspective, thus removing the possibility of that mechanism.

I see your point, but masking the framing with a session-based
mask reopens the issue of multiplexing for intermediaries, as
it will not be possible to guess the key from the masked stream
and it will not be possible to find the unmasking key without
access to the stream.

IMO that was the reason some of us insisted on the per-frame mask
only.

I could personally live with a session-dependant mask if we only
masked the payload and not the framing, but as it is, it reopens
an old can of worms.

Regards,
Willy

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Sat, 29 Jan 2011 19:46:31 +0100

>server-provided per-connection mask and a client-provided per-packet mask.

There is no reason why a server developer who cannot be bothered to pro-
perly validate the handshake will employ a random number generator that
is difficult to predict in generating this mask. Odds are if developers
have to get handshake validation right, and also need to get generating
the mask here right, that they will make mistakes with both. This also
increases the risk that some developers will think the protocol provides
integrity or confidentiality or other features when it does not.

I don't see how this will improve overall security in practise, unless
someone can show that it is insufficient to validate the handshake. And
the cost isn't just more operations per byte, you also have to maintain
more state; and I would expect people who'd like to have this added will
not like it if the scheme allows servers to pick a mask that translates 
to "do nothing" which would re-open the "optional masking" debate.

It's easy to understand "A proper handshake looks like this; if it does
not, refuse the connection and you are safe"; understanding "also use a
cryptographically secure random number generator, making sure its state
isn't exposed through other parts of the system, to generate a per-
connection mask and mix it into the decoding process, then your server
will get confused if under attack" is not so easy. And there's xkcd 424.

Ultimately the argument here is that by making the protocol more complex
we can aid people in implementing it correctly. I do not recall anyone
offering good evidence in support of that argument back when we talked
about the "amateur programmer"; short of someone offering such evidence,
or showing that in practise properly validating the handshake is not
enough, I don't think we should consider this.
-- 
Björn Höhrmann · mailto:[email-masked] · http://bjoern.hoehrmann.de
Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de
25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/

---

From: John Tamplin <[email-masked]>
Date: Sat, 29 Jan 2011 14:15:08 -0500

> possibility of that mechanism.

One of the objections to the options not including everything you need to
mask in the frame itself is the need to maintain state (even if it is a
small amount) in busy intermediaries and the difficulties that imposes on
analyzing captured frames (you have to get every frame including the
handshake to analyze anything).

-- 
John A. Tamplin
Software Engineer (GWT), Google

---

From: Adam Barth <[email-masked]>
Date: Sat, 29 Jan 2011 17:59:52 -0800

> masked the payload and not the framing, but as it is, it reopens

I'm not really sure I understand how session-dependent masking incurs
much of a cost for multiplexing intermediaries.  At most, the
intermediary would need to maintain 32-bits of state per stream, which
is less than the TCP control blocks it needs to maintain anyway.

> handshake to analyze anything).

Again, the overhead that session-dependent masking incurs is
infinitesimal.  For example, the state required to analyze logs of
captured frames is less than the state required to remember which
parties were communicating (e.g., even just their IPv4 addresses).

Kind regards,
Adam

---

From: Willy Tarreau <[email-masked]>
Date: Sun, 30 Jan 2011 07:49:08 +0100

Hello Adam,

> is less than the TCP control blocks it needs to maintain anyway.

It's not a matter of memory but a matter of knowing what key to use with
each multiplexed message. I think my explanation was not clear in fact.
Let's see two examples.

The first one is a server receiving multiplexed streams in a single
connection from a proxy which aggregates them from multiple clients.
The stream looks like this :

  [ key1 ] [ msg1 ] [ key2 ] [ msg2 ] ... [ keyN ] [ msgN ]

Each msg is composed of a masked framing followed by a masked payload.
The server has no way to know which client each message comes from until
he has unmasked the message. One proposal could consist in having the
server always emit the same random on a given connection, but it could
be argued that this voids the effect of the random then. It would also
strongly tie clients to connections, which limits the usefulness of
multiplexing, where connection pools are much more efficient.

The second example involves a proxy which acts on a multiplexed stream.
For instance, it could be a filter to prevent some terms from appearing
in chat discussions, or sort of an IDS trying to block exploits for known
bugs affecting servers. Or it could also be a cache in an auto-completion
system for a search engine, which proposes most common searched words
without bothering the servers, or simply an automatic indexing system.
Anything which has to work inline on the stream.

This component receives the same stream as above and forwards it to the
next hop, be it the server or another proxy. This time it has no way to
find the server's key from the connection. It just sees a message stream
with a key at the beginning, and no way to decode the extension data.

I see 3 solutions for these issues :
  - always prepend a stream ID at the beginning of the message when doing
    multiplexing. This is annoying because it means that the frame format
    is not the same depending on multiplexing or not.

  - don't depend on a per-session key (as we have right now). Like John,
    I'd prefer that we don't have to maintain a state and I'd like to be
    able to analyse network traces without having to rewing back 5 minutes
    to get the server key, but it is just a preference in my case, I'm not
    strongly opposed to the per-state key. However it would limit load
    balancing techniques since there would be no way to send a frame to be
    analyzed to a component from a pool which does not know the key.

  - don't mask the framing, just mask the payload. It then becomes possible
    to send a stream ID or even the server key as an extension for all other
    components behind to be able to decode the stream. Or we could also send
    clear-text frames assuming we're already in the clean room.

That said, we designed the handshake to prevent cross-protocol attacks and
we're saying that we're still fragile to clients sending a POST. Surely we
failed to address all issues somewhere and need to work a bit more on the
handshake. I already see a few points :
  - once a method is proposed, make it mandatory on the server side
  - make it mandatory to reject any incoming request with a body

At one point, we should probably consider that if all the MUST of the spec
have been deliberately ignored by the server-side implementation, we have
limited abilities to protect it against anything. It could as well decide
that if it did not see a valid nonce in the request, then the server key
is not computed and remains zero. So the client can still blindly send
anything to it.

We can't design a protocol that remains totally safe when implementers don't
bother to open the spec. However we can (and should) protect the most compliant
implementations against a maximum number of possible issues.

Regards,
Willy

---

From: Adam Barth <[email-masked]>
Date: Sat, 29 Jan 2011 23:47:46 -0800

>  [ key1 ] [ msg1 ] [ key2 ] [ msg2 ] ... [ keyN ] [ msgN ]

Why mask between the proxy and the back-end server at all?  The
protocol you describe above isn't WebSockets anyway.  Since you're
free to speak whatever protocol you like, you might as well terminate
the masking at the proxy.

Kind regards,
Adam

---

From: Willy Tarreau <[email-masked]>
Date: Sun, 30 Jan 2011 08:55:24 +0100

On Sat, Jan 29, 2011 at 11:47:46PM -0800, Adam Barth wrote:
> Why mask between the proxy and the back-end server at all?

Because at the moment, masking has been made mandatory in the direction
from the client to the server.

> The protocol you describe above isn't WebSockets anyway.

I don't know why you're saying that given that we've talked a number
of times in the past about the need to be able to evolve in the
direction of multiplexing even if we don't implement it right now.

Willy

---

From: Adam Barth <[email-masked]>
Date: Sun, 30 Jan 2011 00:11:44 -0800

> from the client to the server.

The proxy isn't a client.  It's a proxy.  From you description, it
sounds like the proxy is acting as a WebSockets server and then as a
WillyTarreauSockets clients to talk to a WillyTarreauSockets server.

> direction of multiplexing even if we don't implement it right now.

Unless and until we extend WebSockets to include multiplexing, the
protocol you're describing isn't WebSockets.  It's
WillyTarreauSockets.

Kind regards,
Adam

---

From: Willy Tarreau <[email-masked]>
Date: Sun, 30 Jan 2011 10:01:02 +0100

> WillyTarreauSockets clients to talk to a WillyTarreauSockets server.

No, it's talking to a standard WebSocket server that will be known for
supporting a multiplexing extension. I've already said it, look what
happened to HTTP. There are many sites running with front proxies
aggregating traffic over connection pools for standard HTTP servers.
It was done because it dramatically improved their processing speed.
It will be even more important with WebSocket where long connections
are expected to be common.

> protocol you're describing isn't WebSockets.  It's WillyTarreauSockets.

Call it as you like. I'm not trying to define my protocol as you seem to
imply it by putting my name on it. I'm just trying to remind people that
some extensions will be much harder to implement if possible at all with
certain masking choices.

We have designed a protocol that supports extensions (cf 4.8), and it
was even said that the protocol should evolve via extensions instead of
versions because "versioning is anti-pattern". Stream multiplexing has
been identified as something we'll want to introduce at one point
because it makes a lot of sense on the server side and looks like a
natural evolution of the protocol.

Thus if we mask the framing with a stream-specific key, we'll mask the
extensions as well and we won't be able to later implement stream
multiplexing as an extension and we'll have to change the framing for
that, which is a bit contrary to extensibility as defined in 4.8.

I'd like that we'd be careful not to break extensibility.

Once again, I see how you want to protect the laziest servers against
HTTP->WS attacks, but 1) I'm sure it's not the only solution, 2) if
we do this we should probably only mask payload and not framing, and
3) I'm still wondering why someone who can send a POST request from a
browser to a WS server could not make a native WS connection to send
real traffic the normal way, but that's another debate.

Regards,
Willy

---

From: Andy Green <[email-masked]>
Date: Sun, 30 Jan 2011 09:47:19 +0000

> using non-WS clients (e.g., the FORM tag) to be sent to a WS server

Could someone elaborate on the sequence of events there?  The masking 
key itself includes a nonce sent back by the server, is that not enough 
to disallow canned clientside content working from scratch?

The 32-bit frame key sent by the client is not used directly but is 
hashed with the masking key which contains random info from the server.

-Andy

---

From: Maciej Stachowiak <[email-masked]>
Date: Sun, 30 Jan 2011 04:30:01 -0800

On Jan 30, 2011, at 1:47 AM, Andy Green wrote:

> Could someone elaborate on the sequence of events there?  The masking key itself includes a nonce sent back by the server, is that not enough to disallow canned clientside content working from scratch?
> 
> The 32-bit frame key sent by the client is not used directly but is hashed with the masking key which contains random info from the server.

That's the case in the current draft. However, the Chairs have declared consensus to change this so that only the 32-bit mask included in the message is used for masking, thus regressing protection against this threat model. Adam proposed a lightweight way to bring back stronger protection against non-WS clients. For what it's worth, Adam's solution would address my objection.

Also noteworthy, it results in trivial computational overhead (an extra 32-bit XOR operation per frame) and trivial state overhead (32 bits per connection). It also does not use real crypto. This should address most objections to the AES and XOR+HMAC alternatives in the poll.

Regards,
Maciej

---

From: Eric Rescorla <[email-masked]>
Date: Sun, 30 Jan 2011 08:47:10 -0800

> multiplexing, where connection pools are much more efficient.

Let's take a step back here:
If you're going to mux connections from multiple clients, you
absolutely want the
ultimate back-end server to know which client they came from, if for no other
reason than it's generally attractive to tie requests into a single
context (e.g.,
once a client has authenticated overTLS you don't force reauthentication). So,
I don't really see the problem of attaching a stream-id.

I don't see that there is a useful variant of WebSockets that has
multiplexed traffic
by different clients on the same TCP connection. That's some other,
non-WS protocol
and I agree with Adam that it doesn't require masking at all.

-Ekr

---

From: Andy Green <[email-masked]>
Date: Sun, 30 Jan 2011 17:12:34 +0000

On 01/30/11 12:30, Somebody in the thread at some point said:

> That's the case in the current draft. However, the Chairs have declared
> consensus to change this so that only the 32-bit mask included in the
> message is used for masking, thus regressing protection against this
> threat model. Adam proposed a lightweight way to bring back stronger
> protection against non-WS clients. For what it's worth, Adam's solution
> would address my objection.

Well, not changing it will also make that observation redundant.

> Also noteworthy, it results in trivial computational overhead (an extra
> 32-bit XOR operation per frame) and trivial state overhead (32 bits per
> connection). It also does not use real crypto. This should address most
> objections to the AES and XOR+HMAC alternatives in the poll.

Maybe it is better to follow Greg's idea about bringing the masking into 
the extensions scheme now.  Servers and clients can both enforce what 
kind of masking they think is best then, and introducing a new scheme 
needn't delay the standard as a whole.  I mean maybe next week a better 
new scheme appears (or the utility of masking rightly get questioned by 
more people) and this way a new or no masking scheme can be slipstreamed 
into use without spinning the standard.

You believe that having 8 bytes in clear before the masking is 
dangerous?  If so do you have any idea about specifically what it would 
be dangerous to?  What about sticking the extension zone, usually zero 
bytes, before the length count so it could be encrypted?

-Andy

---

From: Willy Tarreau <[email-masked]>
Date: Sun, 30 Jan 2011 22:25:04 +0100

> I don't really see the problem of attaching a stream-id.

Exactly. And if that stream ID is located where it is supposed to be (in the
extension data), it will be masked.

Willy

---

From: "Thomson, Martin" <[email-masked]>
Date: Mon, 31 Jan 2011 06:15:40 +0800

> extension data), it will be masked.

Perhaps the stream ID can be added before the masking key, in the clear.  After all, we're talking about a negotiated extension here.  It only appears when both sides have agreed to its necessity.

On the mechanism... The only extension that I would suggest is that M1 might be better derived from a combination of server and client produced noise.  That would let the browser have some say on the length of sequence.  For instance, if the server wanted to poison an intermediary, they could set a really small M1 to increase their chances of hitting the right combination.

Anything less than or equal to the frame mask in length is going to be as weak as having no M1 at all - leaving that in server control seems irresponsible.

--Martin

---

From: Eric Rescorla <[email-masked]>
Date: Sun, 30 Jan 2011 14:29:45 -0800

> extension data), it will be masked.

As Adam said, this isn't WebSockets. It's WillyTarreauSockets. Frame
the WS messages
and add the stream-id in the framing. This is better in any case
because it avoids intermixing
meta-data supplied by the proxy with data supplied by the client.

-Ekr

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 31 Jan 2011 10:09:33 +1100

> the masking at the proxy.

This is an oft-repeated argument whenever the topic of intermediaries
is discussed.

The counter argument is that data centres are built from components
sourced from multiple vendors and that it is REALLY important that the
standards apply within the data centre as well as without.   We are
not all google who have the luxury of developing their own private
internal protocols.

Note that I'm please to see that Adam does now recognise the desire to
not mask within the data centre, and his view that this is outside the
standard goes a long way to explain why he is opposed to masking as an
extension.

Chairs - can we get a consensus call on this point - that
intermediaries (even those running extensions like mux) talking to
servers should be covered by the protocol that we standardise.

regards

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 31 Jan 2011 10:14:59 +1100

>  [ key1 ] [ msg1 ] [ key2 ] [ msg2 ] ... [ keyN ] [ msgN ]

I think this example shows the folly of having the key as something
outside the framing.

If the key was sent as extension data then we would have:

 [<key1>msg1] [<key2>msg2 ] ... [<keyN>msgN]

If we were to add a mux extension, then the chanId could also go into
the extension data:

 [<chanID,key1>msg1] [<chanID,key2>msg2 ] ... [<chanID,keyN>msgN]

The choice of using session based masking vs frame based masking would
then be independent of whatever extension might be applied  (I would
still favour frame based masking, but could live with session masking
in this scenario).

regards

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 31 Jan 2011 10:29:00 +1100

> I don't really see the problem of attaching a stream-id.

Because we designed framing with extensions so that they could be used
for things like MUX.   But now that framing is masked it means that
all extensions must understand masking, making it impossible to have
both session based masking and a session ID within the extension data.

Of course the session ID could be prepended like:

  [sessionID][key][message]

But that would mean the MUX "extension" would be changing framing and
would not work with any other intermediaries or infrastructure that
was not aware of the MUX extension.

This shows the folly of not putting meta data like masking keys and
stream IDs in the frame extension data.  Once one "extension" breaks
out of this model, it will break all intermediaries and infrastructure
and force all other extensions to do the same.

---

From: Eric Rescorla <[email-masked]>
Date: Sun, 30 Jan 2011 16:16:43 -0800

On Sun, Jan 30, 2011 at 3:29 PM, Greg Wilkins <[email-masked]> wrote:
> for things like MUX.

I'm not sure what "me" you're talking about. That certainly was never
my intention
and I think it's quite a bad idea.

-Ekr

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 31 Jan 2011 11:41:07 +1100

> and I think it's quite a bad idea.

Eric,

are you saying that you don't think mux is a good idea, or that mux as
an extension is not a good idea?

Eitherway, I invite you to review the list archives, where you will
see that MUX was definitely used as an exemplar  throughout the entire
framing/extension discussions:

http://www.google.com/search?client=ubuntu&channel=fs&q=ietf+hybi+archive+frame+multi+extension+&ie=utf-8&oe=utf-8#sclient=psy&hl=en&q=multiplex+extension+site:www.ietf.org%2Fmail-archive%2Fweb%2Fhybi%2F&aq=f&aqi=&aql=&oq=&pbx=1&fp=8bc3ae5f5881b3d2

If the frame extension data is not to be used for things like masking
keys and MUX stream IDs, then can you give me an example of what you
think the frame extension data could be used for?

regards

---

From: Eric Rescorla <[email-masked]>
Date: Sun, 30 Jan 2011 16:51:56 -0800

> an extension is not a good idea?

I think mux as an extension is a bad idea: it intermixes data supplied by the
client with data supplied by the proxy.

> http://www.google.com/search?client=ubuntu&channel=fs&q=ietf+hybi+archive+frame+multi+extension+&ie=utf-8&oe=utf-8#sclient=psy&hl=en&q=multiplex+extension+site:www.ietf.org%2Fmail-archive%2Fweb%2Fh…

Yes, I'm sure many people had it in mind. But it's not something I
agree with, and
since there wasn't ever a consensus call on this approachI don't
consider it a trumping
argument when we're discussing masking.

> think the frame extension data could be used for?

My experience is that extension fields are an escape hatch that is
sometimes useful
in the field after the protocol is deployed. Such escape hatches often
don't come with
particular rationales. I wouldn't cry if it were removed, however.

-Ekr

---

From: John Tamplin <[email-masked]>
Date: Sun, 30 Jan 2011 20:58:47 -0500

> client with data supplied by the proxy.

What data from the proxy is it intermixing?  How is this different than HTTP
going through a proxy and the proxy adding its own content to the proxied
content?  Are you suggesting that HTTP proxies should not be speaking HTTP
extended with additional headers, but should have instead invented a new
protocol for talking to servers?

One of the primary use-cases I see for a MUX extension to WebSockets is to
aggregate connections from one browser to one server (or a cluster of
servers pretending to be one).  For example, if WebSockets is successful,
you will wind up with different modules on a page contacting their own
backends over WebSockets, and having multiple tabs open you could easily
wind up with a large number of persistent connections.  This could easily
cause developers to not switch Comet-style uses to WebSockets because of the
increased server load that would be caused - I know this is definitely a
deployment concern within Google.

So, I think browsers will need to implement a MUX extension in order to
aggregate connections to to the same server to reduce the number of
persistent connections to a manageable level.  In this case, the "proxy" is
the same as the client.

> argument when we're discussing masking.

Part of the way we got past the endless discussions on framing was to show
that all the ideas people had about what sort of things they might want to
do with WebSockets was to show that the extension mechanism allowed that to
be added later in an extension without impacting implementations of the base
protocol.

To now discard those things during the discussion of masking is to discard
the hard-won consensus on framing as well.

---

From: Maciej Stachowiak <[email-masked]>
Date: Sun, 30 Jan 2011 19:50:11 -0800

On Jan 30, 2011, at 5:58 PM, John Tamplin wrote:

> What data from the proxy is it intermixing?  How is this different than HTTP going through a proxy and the proxy adding its own content to the proxied content?  Are you suggesting that HTTP proxies should not be speaking HTTP extended with additional headers, but should have instead invented a new protocol for talking to servers?
> 
> One of the primary use-cases I see for a MUX extension to WebSockets is to aggregate connections from one browser to one server (or a cluster of servers pretending to be one).  For example, if WebSockets is successful, you will wind up with different modules on a page contacting their own backends over WebSockets, and having multiple tabs open you could easily wind up with a large number of persistent connections.  This could easily cause developers to not switch Comet-style uses to WebSockets because of the increased server load that would be caused - I know this is definitely a deployment concern within Google.

For muxing at the client, these masking issues don't matter. The browser will not do anything different.

It's specifically the hypothetical case of muxing proxies, which take connections from multiple clients and combine them before farming out to endpoint servers, that introduce complications. It's not really clear to me if the same muxing scheme is necessary appropriate for multiplexing at the client and multiplexing at a proxy.

For a muxing proxy, you can either unmask and redo masking (necessary anyway in the protocol as currently spec'd) or introduce session IDs before the frame. Passing through pre-existing infrastructure is not a concern in this case, since the proxy is talking to a server inside the same data center in this scenario.

Regards,
Maciej

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 31 Jan 2011 06:41:30 +0100

On Sun, Jan 30, 2011 at 02:29:45PM -0800, Eric Rescorla wrote:
> the WS messages and add the stream-id in the framing. This is better
> in any case because it avoids intermixing

I don't see how this is different, perhaps I'm not getting what you mean.
Could you give an example of how some messages would be framed with your
proposal (let's call it EricRescorlaSockets if you like).

Thanks,
Willy

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 31 Jan 2011 07:06:53 +0100

> Perhaps the stream ID can be added before the masking key, in the clear.  After all, we're talking about a negotiated extension here.  It only appears when both sides have agreed to its necessity.

I see your point, but the negociation should be end-to-end and the client
doesn't care about what's in the middle.

In fact what I find annoying is that we have designed something in theory
extensible, but in practice we're doing everything we can to ensure we
won't ever use extensions. Masking and Multiplexing can't be done as
extension. Probably if we look a bit closer we'll find that compression
can't either. Due to frame masking we have to define a different framing
format for each combination we think of. This is not what I'd call an
extensible design. Also, we should keep in mind that a design which does
not easily let whatever component we can think of integrate with existing
applications will necessarily have to change once deployed (and servers
will have to support both). That's what happened with HTTP. The Host
header became mandatory some time after the protocol was widely deployed,
because it allowed much more flexibility.

With a per-frame mask, we can still decode the framing to find other important
extensions. With per-(frame+stream) mask, we can only do that if the framing
is not masked, otherwise we need different formats for different types of
streams (and different code parts on the server side).

> Anything less than or equal to the frame mask in length is going to be as weak as having no M1 at all - leaving that in server control seems irresponsible.

Not necessarily. I see Maciej's point on this. What he wants is to make it
mandatory for the server to use a negociated mask, so that a too lazy server
cannot be spoon-fed some WS requests via a from sent as a POST request. Still
I'm sure that what will happen on such lazy servers will look like this :

  new_session()
  {
    session = calloc(1, sizeof(*session));
    session->key = get_header("Sec-WebSocket-Key");
    if (session->key)
       init_server_nonce(session);
    return session;
  }

  init_server_nonce(session)
  {
     session->M1 = random();
     session->nonce = compute_nonce(session->key);
     send_header("Sec-WebSocket-Nonce", session->nonce);
  }

See above ? If the server ignores the fact that client's key is missing,
it's very easy not to compute a nonce and then not to compute the random
either, which will remain zero (we're talking about lazy servers after
all). In this case, yes, M1 serves no purpose if the server is too lazy
and does not compute it.

We can't really force lazy implementers to implement the most important
parts of the protocol if those parts bring them nothing but complexity.

For instance, I'm pretty sure that on the client side, only browsers
will implement a real key and will check it. Simpler clients will just
send a constant key (possibly with their name in it) and won't ever
check the returned nonce since it brings them nothing.

Regards,
Willy

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 31 Jan 2011 17:14:47 +1100

On 31 January 2011 14:50, Maciej Stachowiak <[email-masked]> wrote:
> For a muxing proxy, you can either unmask and redo masking (necessary anyway
> in the protocol as currently spec'd) or introduce session IDs before the
> frame.

In order to unmask at the proxy, it would need to effectively be the
endpoint of the connection and accept the handshake. The problem with
that scenario is  that having the intermediary accept the WS
connection is a different semantic to allowing the application server
to accept/reject handshakes.

I'm sure there will be some proxy's that do want to be the endpoint,
but I'm also sure that there are some that will simply want to whack
on a streamId and pass the packets on over a shared connection with
little or no processing.

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 31 Jan 2011 07:15:15 +0100

On Sun, Jan 30, 2011 at 07:50:11PM -0800, Maciej Stachowiak wrote:
> in the protocol as currently spec'd)

except that if each frame is masked with a server-provided key, the server
won't be able to know what key to use to decode each frame.

> or introduce session IDs before the frame.

which basically means that code will need to be changed on the server before
this is possible, so that a new frame format is supported. It's a shame to
define a framing and not being able to use it at large scales without
redefining it :-/

Willy

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 31 Jan 2011 07:18:21 +0100

> I'm sure there will be some proxy's that do want to be the endpoint,

it's even certain because they won't always be able to decide for the
server what extensions to negociate. It's much better for them to pass
the connection to the appropriate server and adjust params afterwards
with the client.

Willy

---

From: "Alexander Philippou" <[email-masked]>
Date: Mon, 31 Jan 2011 08:30:13 +0200

> For instance, I'm pretty sure that on the client side, only browsers will implement a real key and will check it. Simpler clients will just send a constant key (possibly with their name in it) and won't ever check the returned nonce since it brings them nothing.

Spot-on.

Alexander

---

From: Maciej Stachowiak <[email-masked]>
Date: Mon, 31 Jan 2011 06:58:08 -0800

> to accept/reject handshakes.

How would you solve this problem if masking didn't exist? The WebSocket protocol has no provision to do an additional handshake over an existing connection, and presumably would not even if multiplexing were added. So the proxy has to accept the handshake, unless it uses something other than WebSockets to talk to the app server.

> on a streamId and pass the packets on over a shared connection with

That doesn't seem compatible with the idea that accept/reject must be up to the application server. For that to happen, the app server would need to see a new client handshake.

Regards,
Maciej

---

From: John Tamplin <[email-masked]>
Date: Mon, 31 Jan 2011 11:56:58 -0500

On Mon, Jan 31, 2011 at 9:58 AM, Maciej Stachowiak <[email-masked]> wrote:
> How would you solve this problem if masking didn't exist? The
> WebSocket protocol has no provision to do an additional handshake
> over an existing connection, and presumably would not even if
> multiplexing were added.

Actually, I think it has to be able to perform a handshake for a new
logical channel, if a multiplexed connection is to be treated the same
as a non-multiplexed one.  Imagine you have a non-MUX client and
server connected by a network that includes a mux/demux pair.  The
endpoints should behave identically to if they were connected without
multiplexing, which means the server has to see the handshake so it
can accept requested extensions and can reject based on the origin,
authentication credentials, etc.

So, in my current MUX extension design, AddChannel effectively
behaves as a handshake of a new connection.

---

From: Bruce Atherton <[email-masked]>
Date: Mon, 31 Jan 2011 09:58:25 -0800

> How would you solve this problem if masking didn't exist? The WebSocket protocol has no provision to do an additional handshake over an existing connection, and presumably would not even if multipl…

We already talked about this[1].

This "modest enhancement" would result in real costs in terms of 
debugging. Over the span of the internet and the life of the protocol, 
it wouldn't surprise me if the cost was in the tens of millions of 
dollars, perhaps more. I can't see the benefits make it worth that.

[1] http://www.ietf.org/mail-archive/web/hybi/current/msg05498.html

---

From: Maciej Stachowiak <[email-masked]>
Date: Mon, 31 Jan 2011 10:39:33 -0800

> behaves as a handshake of a new connection.

Would AddChannel include all the same information that's in the client handshake? New channel on existing connection from the browser isn't the same semantic as new mixed in channel from an entirely different client. For instance, in the former case, you can assume any Cookie headers present in the original header are still valid. In the latter case, you cannot.

In any case, assuming multiplexing conveys the equivalent of a full handshake, I believe it gives multiplexing servers what they need to unmask at the mux point.

Regards,
Maciej

---

From: John Tamplin <[email-masked]>
Date: Mon, 31 Jan 2011 13:55:44 -0500

On Mon, Jan 31, 2011 at 1:39 PM, Maciej Stachowiak <[email-masked]> wrote:

> Would AddChannel include all the same information that's in the client
> handshake? New channel on existing connection from the browser isn't the
> same semantic as new mixed in channel from an entirely different client. For
> instance, in the former case, you can assume any Cookie headers present in
> the original header are still valid. In the latter case, you cannot.
>

The current proposal simply includes headers if they are different from
(including not present) those included in the original physical-channel
handshake.  So, a cookie header that is different would be sent in the
AddChannel, while one that was the same (even if from a different client)
would not.  On the server end, after the demux, processing a new connection
would be identical regardless of whether it was a physical connection or an
AddChannel on a mux'd connection.

> In any case, assuming multiplexing conveys the equivalent of a full
> handshake, I believe it gives multiplexing servers what they need to unmask
> at the mux point.
>

Right, but the question is if that is desirable.  The demux may be very busy
handling lots of requests -- it would be desirable if the processing
required to pass the payload to the ultimate server were minimal.