Subject: Re: [hybi] Masked framing VS mask in frame

From: John Tamplin <[email-masked]>
Date: Tue, 1 Mar 2011 03:27:17 -0500

On Tue, Mar 1, 2011 at 2:42 AM, Andy Green <[email-masked]> wrote:
> Well, I feel your pain, but it's notable nothing has been suggested to need
> that extension area per-packet and it's legitimate to ask for an example of
> what would need it and if we can get rid of it.  I'm not asking out of the
> blue it is part of looking at moving masking down the packet and make sure
> it can't run on into the undefined extension area in a controllable way.
>
> If there are reasonable examples I am happy to accept that and forget about
> it.

>From memory, a couple of things were discussed that would need to send
extension data:
 - MIME types or other metadata for content
 - A more advanced compression algorithm might want to send a compression
   dictionary, or identify separate streams with separate compression state

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

---

From: Andy Green <[email-masked]>
Date: Tue, 01 Mar 2011 08:47:36 +0000

On 03/01/2011 08:27 AM, Somebody in the thread at some point said:
> On Tue, Mar 1, 2011 at 2:42 AM, Andy Green<[email-masked]>  wrote:

Thanks.  Extensions sending extension data generally I could already 
imagine as being needed.  But as it stands, the extension data is 
coupled to a specific packet + payload, right inside it.

Both those examples seem like they could work fine outside of that, 
using extended opcodes already allowed for and bound to a stream, the 
default stream or a specific muxed stream.

Whatever the extension data is that binds itself to a stream using the 
current scheme, it has to be generated synchronous to the stream payload 
content since its content goes into a payload packet.  So it would 
always be possible to generate the same content in a reliable way in a 
separate frame before the payload content it wanted to impact.

It'd leave the existing spec a lot cleaner that way to break extension 
data out into its own frame with reserved, extended opcodes and 
extension data as normal payload, rather than have this really not 
specified extension data area of unknown length inside every frame.

-Andy

---

From: John Tamplin <[email-masked]>
Date: Tue, 1 Mar 2011 03:57:09 -0500

On Tue, Mar 1, 2011 at 3:47 AM, Andy Green <[email-masked]> wrote:
> Both those examples seem like they could work fine outside of that, using
> extended opcodes already allowed for and bound to a stream, the default
> stream or a specific muxed stream.
>
> content since its content goes into a payload packet.  So it would always be
> possible to generate the same content in a reliable way in a separate frame
> before the payload content it wanted to impact.
>
> It'd leave the existing spec a lot cleaner that way to break extension data
> out into its own frame with reserved, extended opcodes and extension data as
> normal payload, rather than have this really not specified extension data
> area of unknown length inside every frame.

Right, but what got us to where we are is that we could not agree on
whether using new opcodes (and nesting them) or having separate
extension data was the better approach, and within that we couldn't
get the details of either of them agreed on.  So, we wound up with
what we have, which can be used to implement any of those proposed
extension mechanisms.  Maybe things are different from last summer,
but I do not know why to expect we can define the extension format now
when we couldn't then.

As one example, if you use the nested opcode approach, you absolutely
can't interpret anything in the payload past an extension you don't
understand.  At least with a separate extension area, if we came up
with a tag/value approach you could imagine being able to skip
extension data that you didn't understand.  So, I tend to think of
extension by opcode as mandatory extensions, and extension by metadata
as optional ones, but that is just me and another thing we never could
agree on.

I urge you to read the endless discussions last summer where exactly
these options were discussed before suggesting them.

Also, I do not think it is necessary to define it in the base spec,
since a future revision could define that there is no extension data
and allocate adjacent reserved bits to the opcode field for extension
opcodes, and no implementation of the current spec would be broken by
that change.

---

From: Andy Green <[email-masked]>
Date: Tue, 01 Mar 2011 09:17:17 +0000

On 03/01/2011 08:57 AM, Somebody in the thread at some point said:

Hi -

> As one example, if you use the nested opcode approach, you absolutely

Sorry I am not talking about any nesting but sequential normal frames. 
For example:

  [BINARY_OPCODE hdr + len][payload]
  [EXTENDED_OPCODE hdr + len][payload (it is extension data, eg, 
compression dictionary)]
  [BINARY OPCODE hdr + len][payload]
  ...

there is no problem with following the stream even if I don't understand 
the extension, since it's a normal frame with length and payload defined 
just a funny opcode.

> these options were discussed before suggesting them.

I am urged to read endless discussion... ^^

> opcodes, and no implementation of the current spec would be broken by

Except the uncertainty of having zero or more undefined bytes in the 
middle of every packet raises issues about moving masking key past it, 
and parsing the frame with snoopers, it's also kind of strange to see 
such an area with at least no defined length control over it in a protocol.

Anyway thanks for engaging with my question: I made my suggestions if it 
doesn't sounds interesting to anyone else I'll let it lie.

-Andy

---

From: "Pat McManus @Mozilla" <[email-masked]>
Date: Tue, 01 Mar 2011 09:37:47 -0500

On Tue, 2011-03-01 at 15:42 +1100, Greg Wilkins wrote:
>   However, I do not think
> they have well communicated the technical case against it. 

* The mask increases the security properties of the protocol by making
it safe for transmission across transparent http proxies with certain
classes of bugs. This is true for both server (i.e. attacker) provided
data as well more generally true other data sources that should be
masked for transport across legacy http. The hybi archives might qualify
as such a data source. 

* The mask is incredibly cheap to implement. You can do XOR at the rate
of your memory bandwidth. The benefit to "optimizing it away" is at best
marginal even in high bandwidth scenarios.

* transparent and silent proxies are infrastructure elements and their
presence are not always known to clients at extension negotiation time.
Even clients such as websocket intermediaries may not be aware of them,
or they may come and go as routing schemes change.

--> consistent application of masking makes websockets a generally more
robust protocol at an insignificant cost. Creating a path for the
defense to be disabled is penny wise pound foolish.

---

From: "Pat McManus @Mozilla" <[email-masked]>
Date: Tue, 01 Mar 2011 09:40:07 -0500

On Tue, 2011-03-01 at 07:36 +0000, Andy Green wrote:
> Don't forget a packet snooper is screwed by the mask already in current 
> draft, it doesn't know if the packet is client -> server and has a 
> 4-byte mask prepended, or server -> client and lacks it.

Being transported on a stream based protocol, it is screwed whenever it
misses the handshake as it cannot be sure where the frame starts even in
the total absence of an asymmetric mask. If it has the handshake, then
there is no problem, if it misses it then it has to apply a pile of
heuristics - which still seems quite doable with masking (i.e. port
numbers, testing likely bytes for known opcodes, testing them with the
mask, etc..).

-- 
http://www.getfirefox.com/

---

From: Andy Green <[email-masked]>
Date: Tue, 01 Mar 2011 14:58:25 +0000

> numbers, testing likely bytes for known opcodes, testing them with the

Well, you're right.

But two points ameliorate that, one is that the snooper only needs to 
achieve sync at the start of its snooping session and it won't lose it 
again if it's genuinely synced.

The second point is the data on a websocket link is probably critical 
for latency so it will try to issue what it has quite quickly, and 
likely bursty, so sometimes there's no traffic.  If the server makes a 
new frame at a packet boundary you are very likely to find a websocket 
header at the start of the first network packet after a period of being 
idle.

If the data on the link doesn't fit that profile, eg it's audio that's 
always coming at a fixed rate, but the server spilling packets is done 
at a smaller amount of data than the frame length, yeah it'll be 
difficult to know what you're looking at.

-Andy

---

From: John Tamplin <[email-masked]>
Date: Tue, 1 Mar 2011 10:20:53 -0500

On Tue, Mar 1, 2011 at 4:17 AM, Andy Green <[email-masked]> wrote:
> Sorry I am not talking about any nesting but sequential normal frames. For example:
>
>  [EXTENDED_OPCODE hdr + len][payload (it is extension data, eg, compression dictionary)]
> there is no problem with following the stream even if I don't understand the extension, since it's a normal frame with length and payload defined just a funny opcode.

So what if the extension alters the interpretation of the payload?
Say, the extension opcode is for super-compression that was
negotiated?  Are you suggesting that the compressed data follows in
the next frame as if it were a regular frame?  If so, how is it
interpretable by something that doesn't understand the extension?

Also, how does handle compositing extensions -- ie, the foo and bar
extensions, each of which mutate the payload?  If you had nested
opcodes, you would have something like:

BAR_OPCODE [bar(FOO_OPCODE [foo(TEXT_OPCODE, "hello")] )]

If you make each extension a separate frame, I am not sure how you
know how to interpret the result.

> I am urged to read endless discussion... ^^

I am just saying these things were discussed before.

> Except the uncertainty of having zero or more undefined bytes in the middle of every packet raises issues about moving masking key past it, and parsing the frame with snoopers, it's also kind of strange to see such an area with at least no defined length control over it in a protocol.

I really don't see much value in moving any extension data before the
masking -- if we are masking the payload anyway, masking the extension
data seems of little cost and protects us against an extension that
allows attacker-controlled data.

If no extensions are negotiated, the length is 0 (or 4 if the masking
key is considered part of it on the client->server side) and you know
exactly what goes there.  If you later add support for an extension,
the definition of that extension will say how to interpret the area,
which might be zero length, a fixed length field, or some tag/value
format that lets you skip over the extension.

The endpoints have to have negotiated the extension for it to be
present, so they have to know what it means.  The only loser is
transparent intermediaries (including packet sniffers) -- as mentioned
in the current spec, they can't fragment or interpret the payload if
an extension they don't understand is implemented.

---

From: Andy Green <[email-masked]>
Date: Tue, 01 Mar 2011 15:37:20 +0000

On 03/01/2011 03:20 PM, Somebody in the thread at some point said:
> On Tue, Mar 1, 2011 at 4:17 AM, Andy Green<[email-masked]>  wrote:
>> [BINARY_OPCODE hdr + len][payload] [EXTENDED_OPCODE hdr +
>> len][payload (it is extension data, eg, compression dictionary)]
>> [BINARY OPCODE hdr + len][payload] ...
>>
>> there is no problem with following the stream even if I don't
>> understand the extension, since it's a normal frame with length and
>> payload defined just a funny opcode.
>

Sorry John we have been talking at cross-purposes.

> interpretable by something that doesn't understand the extension?

I didn't implement extension support yet, I went and checked and 
"payload length" includes the extension length inside the frame.

     ''The payload length is the length of the
       Extension data + the length of the Application Data.  The length
       of the Extension data may be zero, in which case the Payload
       length is the length of the Application data.''

I thought there was no accounting for any extension data length which 
made it so strange to have it inside, but I was just under the wrong 
impression; even if you don't know what has gone on with extensions or 
how to interpret them, it doesn't make trouble for finding the next 
frame because the length, whatever it is, is accounted for in the 
"payload length".

So no worries, sorry for the noise.

-Andy

---

From: Greg Wilkins <[email-masked]>
Date: Wed, 2 Mar 2011 10:29:04 +1100

> marginal even in high bandwidth scenarios.

That is a hand waive.  It is neither incredibly cheap nor simple when
it is munged in with the framing.

For example In java, we have two type of buffer: direct (kernel space)
and indirect (user space).
Typically by the time we are at the level of sending framing, we
mostly would like to be dealing with kernel space buffers, perhaps
doing a gather write of the headers with the content.    But masking
in the framing means that we need to copy kernal data back into user
space, mask and then put it back to kernel space - UGH!  If SSL is
involved, it get's even uglier.

With incoming data, there is a difficulty looking at kernel space
buffers and it is best to do bulk operations on them.  Masking the
framing means that we needs to copy the data to user space, often only
to discover we don't have the full frame and have to wait for the rest
of it (now holding both a kernel and a user space buffer).

If we mask the payload, then because it is  exchanged with the
application, it is naturally in user space  and we know have been
fully received.   It then is a relatively simple and cheap exercise to
XOR the entire payload.

> robust protocol at an insignificant cost.

Exactly!   So having masking be just an exemplar of an extension that
can mutate payload is great way to achieve consistency in the
protocol.

> Creating a path for the defence to be disabled is penny wise pound foolish.

It is an entirely different question if you make the masking extension
optional or not - Having the ability to turn it off does not mean that
you have to turn it off.    It is wrong to present an inflexible
special case based design as a security benefit.

regards

---

From: "Pat McManus @Mozilla" <[email-masked]>
Date: Tue, 01 Mar 2011 19:01:21 -0500

On Wed, 2011-03-02 at 10:29 +1100, Greg Wilkins wrote:
> That is a hand waive.  

It is not. It is a statement that XOR runs at the rate of memory
bandwidth and that is plenty fast enough; the details of your
implementation not withstanding.

I'm not swayed by an argument that in 2011 an Internet protocol security
feature should be able to be disabled, and thus the attack surface
increased, in order to save the cost of a simple XOR on the data stream.
It is a bad trade off. I was more tempted by the savings when we were
potentially doing complicated hashes or even AES - but with XOR it just
isn't interesting to me. 

I have similar feelings on not masking the header.

Greg, I don't expect you to agree. But you said that such an argument
hadn't been made - and this is the core of mine.

---

From: Brian McKelvey <[email-masked]>
Date: Tue, 1 Mar 2011 16:09:07 -0800

I completely agree.  I dont mean to be hostile, but the browser vendors are the ones concerned about this security issue and indeed exploits that leverage browsers have been the specific attack vector that masking is intended to protect against in all the discussions on this list to date.  Therefore, the onus for making sure that client data is masked should lie squarely on the shoulders of the browser vendors.  That really is common sense, and any argument to the contrary holds no water, IMO.  The only real argument I can recall for making servers require it is just in case there is a bug in some browser that somehow allows unmasked data to be sent.  That is nothing short of a cop-out.

That being said, I would like to see masking apply to the payload and extension data only, whether or not it's required (I care more that the masking is applied only to the payload/extension data than whether its required or not), and implementing it as a (potentially) mandatory extension seems to me a clean way to accomplish the stated goal.  The likelihood that a viable attack accomplishing anything of gravity could be mounted using only the manipulable fields in the framing (length etc) is so remote that it's laughable, but frustratingly, few people seem to be willing to come out and say that directly, even though many have alluded unmistakably to the fact that they agree.

Brian

Sent from my iPhone

---

From: Greg Wilkins <[email-masked]>
Date: Wed, 2 Mar 2011 11:38:31 +1100

On 2 March 2011 11:01, Pat McManus @Mozilla <[email-masked]> wrote:
> It is a bad trade off.

That is not an argument that I am making - at least not in this thread
or on this topic. Please see my original message at the start of this
thread and I certainly did not say that we should turn off masking to
save CPU.

The pros/cons for masking in frame vs masking the frame are made
without reference to the cost of XOR nor without reference to making
masking optional.  I did make the point that having masking in frame
would allow intermediaries to avoid having to demask/remask.  That is
not turning off masking, that is just avoiding decoding/recoding when
the intermediary does not care about the payload.

I do happen to think that masking should be optional - but that is a
separate issue to if the protocol should be flexible and consistent
enough to allow it to be optional.   We can have a flexible and
consistent protocol and still require mandatory masking.

So knocking over the argument that "we should make the protocol less
secure to save the cycles of the XOR" is not relevant because nobody
is making that argument.      I'm sorry if my  objection to your
asserting that masking is cheap, regardless of it's place in the
protocol stack made you think that was the argument I was making.    I
was simply saying that XOR is not always cheap, but it is cheaper if
done on full payloads rather than on partial frames.

> hadn't been made - and this is the core of mine.

I accept that you and others want masking to be mandatory. But I don't
think that means we have to go for a design where we have no choice
but to make it mandatory because it is baked into the framing.

So if we go with the current consensus, that masking is mandatory, do
you have any other objections to mask in frame?

regards

---

From: Brodie Thiesfield <[email-masked]>
Date: Wed, 2 Mar 2011 09:39:28 +0900

> it is munged in with the framing.

Surely there is no necessity to have it turned off completely. For
communications where no masking is desired (whether this is wise or
justified is a separate issue), just set the mask to 0. The only
overhead then is 4 bytes of 0 in front of every payload and the frame
format from client to server doesn't change.

Of course, servers cannot force clients to use a zero or non-zero
mask. That is always going to be the responsibility of the client. The
client can send payload using a 0 mask anytime it wants, and if
selecting mask values by random then 1/256 messages will be using it
anyway. The only part of the spec that the client violates is the one
that requires a random value for the mask, and that part of the spec
is not checked or validated by anything. Therefore the messages are
essentially valid.

To avoid the receiving server from needing to examine the mask to see
if it is 0 or not in order to decode the payload, define a extension
that is a guarantee from the client that all mask values in this
connection are going to be 0. e.g. Sec-WebSocket-Extensions:
zero-mask.

A server receiving and accepting this extension can skip the XOR. Note
that acceptance or not of the zero-mask token can be safely ignored by
the client to no detriment (i.e. just send the 0 masked messages if
that is what it was intending to anyhow). Optionally a client may
special case so that acceptance of the "zero-mask" token means that it
sends 0 mask values, whereas non-acceptance means fully to-spec random
values.

Regards,
Brodie

---

From: Greg Wilkins <[email-masked]>
Date: Wed, 2 Mar 2011 11:56:25 +1100

> format from client to server doesn't change.

This is exactly what is going to happen.   The Jetty Websocket test
client already has a pluggable MaskGen and I have got both NullMaskGen
and FixedMaskGen implementations that can be used for debugging and
other testing where you just don't want the bytes to be changing
randomly.

I think it is unrealistic to think that other non-browser clients will
not also have similar options to send zero masks.  I expect that some
intermediaries might use zero masks as a way to avoid remasking and
that some servers will handle zero masks as special case and skip the
XOR.

Having an inflexible and inconsistent wire protocol will not make
masking mandatory.  The only way that browsers can make masking
mandatory is by making sure their own implementations always use a
good random generator - and that is entirely not enforceable by the
protocol itself.

cheers

---

From: "Pat McManus @Mozilla" <[email-masked]>
Date: Tue, 01 Mar 2011 23:01:52 -0500

> you have any other objections to mask in frame?

Hi Greg,

in my opinion, it is more of the same: a micro optimization that trades
away the property of a full stream mask in return for not very much of
real use.

I think -06 has this right.

---

From: Cedric Vivier <[email-masked]>
Date: Wed, 2 Mar 2011 12:27:57 +0800

> marginal even in high bandwidth scenarios.

Agreed, XOR performance is not an issue.
On the other hand scalability is, and having to XOR the full stream
means it is not possible anymore to use scalable kernel zero-copy
mechanisms to pass data from one point to another without having to
context switch on every message.

With that in mind, I assume the scalability cost of full stream XOR
might be quite significant, especially when it comes to WebSocket
multiplexers (ie. dispatching each particular websocket message to a
specific worker to process it) which otherwise would not do anything
but pass data around with no copy nor context switch.

Regards,

---

From: Greg Wilkins <[email-masked]>
Date: Wed, 2 Mar 2011 16:24:11 +1100

> but pass data around with no copy nor context switch.

... and just to divert this thread back to the topic and avoid another round
of debating how expensive XOR is or isn't....

the whole point of this proposal is that things like multiplexers don't care
about the payload, but do care about framing and extension data.   So if we
have masking in frame as an extension, then a multiplexer will be able to
take a masked payload, prepend some channel meta data and send in a new
frame, but without unmasking and remasking:

Client1->84L1M1M1M1M1P1..P1
                        \
                         MUX->
84L?C1C1M1M1M1M1P1..P184L?C2C2M2M2M2M2P2..P2->server
                        /
Client2->84L2M2M2M2M2P2...P2

L?  length
M? mask
C? mux channel
P? payload

If we can do it this way, then the whole conversation about is XOR too
expensive for intermediaries goes away, because the intermediary does not
need to de-mask and re-mask.

Note that this needs masking to be an extension, so that we can negotiate to
apply it after the MUX extension, otherwise the MUX channel data would need
to be masked and we would need to de-mask and re-mask.

Note also that having masking an extension does not mean it does not have to
be mandatory. We can still insist that it is present in all negotiated
extension orderings if we want.

cheers

---

From: John Tamplin <[email-masked]>
Date: Wed, 2 Mar 2011 00:35:05 -0500

On Wed, Mar 2, 2011 at 12:24 AM, Greg Wilkins <[email-masked]> wrote:

> the whole point of this proposal is that things like multiplexers don't
> care about the payload, but do care about framing and extension data.   So
> if we have masking in frame as an extension, then a multiplexer will be able
> to take a masked payload, prepend some channel meta data and send in a new
> Note that this needs masking to be an extension, so that we can negotiate
> to apply it after the MUX extension, otherwise the MUX channel data would
> need to be masked and we would need to de-mask and re-mask.
>
> Note also that having masking an extension does not mean it does not have
> to be mandatory. We can still insist that it is present in all negotiated

I think when you start saying that extension data is not masked, that is a
very slippery slope and various people have already discussed that we do not
want to allow extension data to be unmasked.  I would instead think that
client->server MUX traffic would be entirely masked, in which case you would
have to do some modification of the payloads anyway if you are aggregating
multiple logical channels (if only one channels contents is included you can
simply use the same key).

I would suggest something like:

MUX_OPCODE COMBINED_LEN MASK_KEY Mask(MASK_KEY,"Channel1 [unmasked channel1
frame] Channel2 [unmasked channel2 frame]")

and you could be clever and as you are copying the logical channel frames
you XOR them with (CHANNEL1_MASK ^ MASK_KEY) and (CHANNEL2_MASK ^ MASK_KEY)
as appropriate.

Also, I expect the initial uses of a MUX extension is for a browser to
aggregate connections to a single server, in which case there is no
unmask/remask involved -- you simply build the MUX frame directly from the
source data.

---

From: Greg Wilkins <[email-masked]>
Date: Wed, 2 Mar 2011 16:54:40 +1100

On 2 March 2011 16:35, John Tamplin <[email-masked]> wrote:
> want to allow extension data to be unmasked.
>

I would expect that from a browser, masking would always be mandatory and
always the first extension.  So all extension data from a browser would be
masked.

>  I would instead think that client->server MUX traffic would be entirely
> masked, in which case you would have to do some modification of the payloads
> anyway if you are aggregating multiple logical channels (if only one
> channels contents is included you can simply use the same key)
>

If intermediaries are involved and they want to be clever with the mask key,
they will just set it to zero.   It is a fallacy to pretend that it can't be
turn off.

> frame] Channel2 [unmasked channel2 frame]")

That looks like you are combining two frames from different clients into a
single frame.  I'm not sure why we would do that.  I expect a MUX channel to
keep separate frames separate and merely tag them with some extension data
to identify the channel.  But then I guess they can keep the same mask key,
so perhaps my concern here is over stated.   But I still believe the
arguments for symmetry, simplicity and flexibility hold.

> you XOR them with (CHANNEL1_MASK ^ MASK_KEY) and (CHANNEL2_MASK ^ MASK_KEY)

That only works if you copy data with a for loops 1 byte at a time.  Most
scalable applications avoid doing that and instead use fast array copy
mechanisms that get delegated to hardware rather than software loops.   But
I do concede that XOR is not expensive  - but the cost of XOR is not the
primary argument for masking in frame.

> unmask/remask involved -- you simply build the MUX frame directly from the

And browser can still mandate that masking is the first extension and thus
mask all MUX data.

I am just fearful anytime I see an argument that there is only 1 true way to
achieve something and that it is OK to have a special case because we know
how it will be used etc. etc.   We need flexibility and agility to adapt to
differing circumstances.  We certainly don't want a system were we start
forcing intermediaries to game the mask keys to achieve scalability.

cheers

---

From: John Tamplin <[email-masked]>
Date: Wed, 2 Mar 2011 01:25:15 -0500

On Wed, Mar 2, 2011 at 12:54 AM, Greg Wilkins <[email-masked]> wrote:

> If intermediaries are involved and they want to be clever with the mask
> key, they will just set it to zero.   It is a fallacy to pretend that it
> can't be turn off.
>

And then they would have to unmask the client frames, which is what I
thought you were trying to avoid?

> arguments for symmetry, simplicity and flexibility hold.

Right, if there is only one logical frame inside the MUXed frame you don't
have to remask anything anyway, so I assumed the discussion was about when
you had more than one.

As for why you might want more than one, think about the way people use
browsers now.  You probably have a number of tabs open, and a number of
long-running AJAX apps in some of them.  Those apps periodically make
connections back to the server to check for new mail, poll for messages,
send user keystrokes, etc.  The server would certainly prefer to have one
connection for all those apps in all those tabs (and you may have modular
apps such that one tab may have multiple connections).  If many of these
messages are small, network utilization would be much better if the small
messages were aggregated into one larger message (of course there is a
latency trade-off here).  Likewise, intermediaries for bandwidth-constrained
networks (such as VPN crossing the public internet or perhaps some mobile
network configurations) will also have interest in aggregating small frames.

> I am just fearful anytime I see an argument that there is only 1 true way
> to achieve something and that it is OK to have a special case because we
> know how it will be used etc. etc.   We need flexibility and agility to
> adapt to differing circumstances.  We certainly don't want a system were we
> start forcing intermediaries to game the mask keys to achieve scalability.
>

I think it is going to be hard to convince browser vendors that some part of
the frame, including extension data that hasn't been invented yet, is safe
to leave unmasked.  I think it is feasible to have the option available and
have browsers enforce it the way they want it, but that idea doesn't seem to
be getting much traction.

---

From: Greg Wilkins <[email-masked]>
Date: Wed, 2 Mar 2011 18:05:42 +1100

On 2 March 2011 17:25, John Tamplin <[email-masked]> wrote:

> And then they would have to unmask the client frames, which is what I thought you were trying to avoid

I  was responding to your example where MUX is done in browser and
there is no intermediary.   I'm concerned about intermediaries having
to demask just to know where the framing boundaries are - and not just
(or even) because of performance.

If browser are doing the muxing, then there is not an issue.     Of
course it is still possible for an intermediary to the MUX the already
MUXed connection from the browser, in which case it would be desirable
for it to not have to demask the frames in order to do it's work.

> Right, if there is only one logical frame inside the MUXed frame you don't have to remask anything anyway, so I assumed the discussion was about when you had more than one.

Well even with 1, the intermediary has to demask  because the frame is masked.
OK, it does not need to demask  the entire frame and it can reuse the
mask on the outbound connection so it can just copy over the payload
after the variable length length fields..... but that is really rather
ugly and a real violation of layered protocols.  Essentially the
intermediaries are gaming the mask algorithm.

> As for why you might want more than one, think about the way people use browsers now.  You probably have a number of tabs open, and a number of long-running AJAX apps in some of them.  Those apps periodically make connections back to the server to check for new mail, poll for messages, send user keystrokes, etc.  The server would certainly prefer to have one connection for all those apps in all those tabs (and you may have modular apps such that one tab may have multiple connections).  If many of these messages are small, network utilization would be much better if the small messages were aggregated into one larger message (of course there is a latency trade-off here).

Really? will the network really care if the TCP/IP packet contains 1
aggregate WS frame or several individual frames?

> I think it is going to be hard to convince browser vendors that some part of the frame, including extension data that hasn't been invented yet, is safe to leave unmasked.  I think it is feasible to have the option available and have browsers enforce it the way they want it,

I'm not trying to convince browser vendors to include extension data
that is either unmasked or not invented yet.   Browser vendors are
free to insist that masking is the mandatory first extension using a
good mask generator - so all data is masked and that is not optional.

I don't think we should be running scared about what browser vendors
may or may not accept.  They have expressed requirements that they
want mandatory masking and I think my proposal allows them to have
that.

> but that idea doesn't seem to be getting much traction.

I have seen several voices in support.

The voices in opposition appear to have miss understood the proposal
and are saying that they want mandatory masking (which can be done) or
that XOR is cheap (which it mostly is and this proposal is not
motivated by the expense of masking).

cheers

---

From: Bruce Atherton <[email-masked]>
Date: Wed, 02 Mar 2011 18:53:27 -0800

On 01/03/2011 6:58 AM, Andy Green wrote:
> header at the start of the first network packet after a period of 
> being idle.
>

Exactly. You may have to scan a few packets before you find the start of 
a frame, but it shouldn't be all that different from scanning an HTTP 
stream looking for the beginning of a request or response. And if you 
know whether to unmask a particular set of packets or not, the heuristic 
for finding the start of a frame becomes a lot easier to work with. This 
is especially true if you know what to look for in the particular 
payload types that are being sent (it could be XML, or fragments of 
audio data that you can try playing).

I would imagine that it won't be uncommon to turn off nagling of the 
packets. Even when they are nagled, I would imagine it would be fairly 
common that a packet containing multiple frames would still start with a 
frame header unless there was a continuous stream of small frames being 
sent. Also, that people might choose smaller frame sizes even in 
applications with large message sizes to reduce the debugging burden as 
well as to reduce the latency of control messages.

As you say, once you have the start of one frame, you are golden and can 
determine everything that comes afterward. But getting there is much 
easier if you can identify candidate packets for starting a frame 
without first unmasking them (supporting Greg's proposal not to mask the 
frame) and if you don't need to test every candidate packet twice 
because the framing tells you whether masking is present or not.

---

From: Brian McKelvey <[email-masked]>
Date: Wed, 2 Mar 2011 20:10:53 -0800

Indeed.  I'm not ready to let this go yet.  It's perfectly logical and reasonable that the frame header can be unmasked while still maintaining mandatory masking of the extension and payload data.  This is a supremely simple change with no actual security risk.  The real possibility that an attack of any substance could be carried out using only the fields manipulable by the js api in the framing (field length) is absurdly remote to the point of non-existence in practicality.

Brian

Sent from my iPhone

On Mar 2, 2011, at 6:53 PM, Bruce Atherton <[email-masked]> wrote:

>> But two points ameliorate that, one is that the snooper only needs to achieve sync at the start of its snooping session and it won't lose it again if it's genuinely synced.
>> 
>> The second point is the data on a websocket link is probably critical for latency so it will try to issue what it has quite quickly, and likely bursty, so sometimes there's no traffic.  If the server makes a new frame at a packet boundary you are very likely to find a websocket header at the start of the first network packet after a period of being idle.
>> 
>> If the data on the link doesn't fit that profile, eg it's audio that's always coming at a fixed rate, but the server spilling packets is done at a smaller amount of data than the frame length, yeah it'll be difficult to know what you're looking at.
>> 
> 
> Exactly. You may have to scan a few packets before you find the start of a frame, but it shouldn't be all that different from scanning an HTTP stream looking for the beginning of a request or response. And if you know whether to unmask a particular set of packets or not, the heuristic for finding the start of a frame becomes a lot easier to work with. This is especially true if you know what to look for in the particular payload types that are being sent (it could be XML, or fragments of audio data that you can try playing).
> 
> I would imagine that it won't be uncommon to turn off nagling of the packets. Even when they are nagled, I would imagine it would be fairly common that a packet containing multiple frames would still start with a frame header unless there was a continuous stream of small frames being sent. Also, that people might choose smaller frame sizes even in applications with large message sizes to reduce the debugging burden as well as to reduce the latency of control messages.
> 
> As you say, once you have the start of one frame, you are golden and can determine everything that comes afterward. But getting there is much easier if you can identify candidate packets for starting a frame without first unmasking them (supporting Greg's proposal not to mask the frame) and if you don't need to test every candidate packet twice because the framing tells you whether masking is present or not.
> 
> _______________________________________________
> hybi mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/hybi

---

From: Brian McKelvey <[email-masked]>
Date: Wed, 2 Mar 2011 20:13:01 -0800

Upon re-reading I wanted to make it clear that when I said "the frame header can be unmasked" I meant transmitted in the clear to begin with.

Sent from my iPhone

---

From: "Martin J. Dürst" <[email-masked]>
Date: Thu, 03 Mar 2011 11:07:31 +0900

Why not make the length of the data needed for a multiplexing extension 
(a multiple of) the length of the mask? That way, the actual payload 
data doesn't have to be touched at all.

Regards,   Martin.

-- 
#-# Martin J. Dürst, Professor, Aoyama Gakuin University
#-# http://www.sw.it.aoyama.ac.jp   mailto:[email-masked]

---

From: "Martin J. Dürst" <[email-masked]>
Date: Thu, 03 Mar 2011 11:57:36 +0900

> connections back to the server to check for new mail, poll for messages,

Just checking, but isn't the main purpose of WebSockets to get rid of 
such checking/polling? The server can just send new mail notifications 
and messages to the client directly.

Regards,   Martin.

---

From: Andy Green <[email-masked]>
Date: Thu, 03 Mar 2011 08:46:41 +0000

> and messages to the client directly.

You're right, but once these TCP connections "go quiet" as part of lack 
of polling, there's a new issue of the ambiguity of silence.

Is it truly because nobody had any new event, or because an endpoint or 
intermediary's Ethernet cable fell out, mobile entered a cell with dead 
internet, etc.

So there'll be a common need to require a background noise of traffic at 
long intervals to confirm the connection is still live and CAN issue 
events still.

-Andy

---

From: [email-masked]
Date: Thu, 3 Mar 2011 02:57:16 -0800

o Masked framing vs mask in frame (original discussion point)

I give +1 for masking inside frame (payload). I agree with what Greg has 
being pointing out
over and over in this thread particularly in preventing intermediaries 
from having to mask/demask 
frames for better scalability.

o Extension field length

It was not clear to me whether understanding the extension field was 
required to parse real
payload. If the extension is intended to be required to correctly parse 
payload, then I will
give +1 for making extension also, which makes the need of extension 
length less important.

One suggestion:

There were many other points being discussed in this thread it was a bit 
hard to follow. One
thing I realized as I was reading this thread was that there were two 
essentially separated 
aspects of protocol design totally mixed in this discussion. One is 
protocol "layering" 
(where to mask, etc.) and protocol between specific entities (e.g. 
extensions). 

I believe when we design protocols, we need first to;

Phase 1:  Define layers (who you are talking to and what their rols are, 
etc.), 

and then;

Phase 2:  Define protocol details between the same layer entities.

>From what I can see, WS protocol seems to already have at least following 
layer entities and intermediaries:

[   App.  ]<------------------------------------------------------->[ App. 
 ]
[ deflate ]<-------------------------------------->[ deflate ]<---->[ 
deflate ] (optional)
[   Ext.  ]<-------------------------------------->[   Ext.  ]<---->[ Ext. 
 ] (optional)
[ Masking ]<-------------------------------------->[ Masking ]<---->[ 
Masking ] (C->S only)
[ Framing ]<--------------------->[ Framing ]<---->[ Framing ]<---->[ 
Framing ]
[   TCP   ]<---->[   TCP   ]<---->[   TCP   ]<---->[   TCP   ]<---->[ TCP  
]

   Client          Std Proxy     WS-aware proxy    App.Lvl GW Server
                  \.............  Intermediaries ............./

I think it is important to define some thing like above first. This 
defines not only the sub layers of 
WebSocket protocol, but also types of intermediaries, roles of each 
protocol entities, the order 
of in/outbound processes (outbound goes downwards through layers, and the 
other way for inbound,
needless to say). Then we start defining how each entities (each 
'<------>' lines) communicate 
with each other (sub-layer protocols). Once we complete this, further 
issues are mostly localized
within the sub-protocol and our discussion will be focused and smoother, 
rather than suddenly turning 
upside down all over layers again in the middle of discussing details of 
the protocol, 
which seems to be happening in the discussion in this thread(and others) 
and taking longer time
than necessary to come to consensus. Defined notion of sub-protocols and 
terminology in phase 1
would help our smooth discussion a lot, too.

"Do we need a light-weight WS-aware proxy?" seems to be a good start 
without looking at headers 
from the beginning, for example.

# this is also relevant to discussion in another thread about what to 
deflate:
http://www.ietf.org/mail-archive/web/hybi/current/msg06352.html 
Again, deflate extension should be right below the app layer, IMO...

my two cents

- Yutaka

[email-masked] wrote on 03/01/2011 11:05:42 PM:

> > Right, if there is only one logical frame inside the MUXed frame 
> you don't have to remask anything anyway, so I assumed the 
> discussion was about when you had more than one.
> 
> > As for why you might want more than one, think about the way 
> people use browsers now.  You probably have a number of tabs open, 
> and a number of long-running AJAX apps in some of them.  Those apps 
> periodically make connections back to the server to check for new 
> mail, poll for messages, send user keystrokes, etc.  The server 
> would certainly prefer to have one connection for all those apps in 
> all those tabs (and you may have modular apps such that one tab may 
> have multiple connections).  If many of these messages are small, 
> network utilization would be much better if the small messages were 
> aggregated into one larger message (of course there is a latency 
> trade-off here).
> 
> > I think it is going to be hard to convince browser vendors that 
> some part of the frame, including extension data that hasn't been 
> invented yet, is safe to leave unmasked.  I think it is feasible to 
> have the option available and have browsers enforce it the way they want 
it,

---

From: Jamie Lokier <[email-masked]>
Date: Thu, 3 Mar 2011 15:16:29 +0000

Brodie Thiesfield wrote:
> mask. That is always going to be the responsibility of the client.

Servers can _easily_ force clients to use a non-zero, varying mask -
by looking at the mask, and if it's consistently the same for several
frames in a row, reject the connection.

Servers may actually do that, if they think it blocks some kind of
attack - or even if they just want to slightly deter connections from
casually written non-browser clients.

-- Jamie

---

From: "Thomson, Martin" <[email-masked]>
Date: Fri, 4 Mar 2011 05:34:55 +0800

> frames in a row, reject the connection.

Of course, if it's possible to get your attack in within those first few frames, then nothing is gained.

---

From: Jamie Lokier <[email-masked]>
Date: Thu, 3 Mar 2011 22:56:23 +0000

> few frames, then nothing is gained.

Quite the opposite.  What would be achieved (I won't call it a "gain"
because I don't think it's a good idea) by proliferation of servers
configured that way would be to prevent the widespread use of
zero-masking legitimate clients, thereby rendering them unavailable as
a hijackable attack vector (in the way that browsers are hijacked by
scripts).

So even if an attack is possible in the first few frames, it won't be
possible to hijack clients to do it - which is the same as masking is
designed to ensure.  So the same motivation is there for paranoid
server writers to refuse zero-masking connections, even if the spec
doesn't say to do that, as there is to have masking in the first place.

-- Jamie

---

From: "Thomson, Martin" <[email-masked]>
Date: Fri, 4 Mar 2011 07:13:05 +0800

On 2011-03-04 at 09:56:23, Jamie Lokier wrote:
> > > by looking at the mask, and if it's consistently the same for 
> > > several frames in a row, reject the connection.
> >
> configured that way would be to prevent the widespread use of zero- 
> masking legitimate clients, thereby rendering them unavailable as a 
> hijackable attack vector (in the way that browsers are hijacked by 
> scripts).
> 

Unfortunately, it doesn't prevent a lazy implementer from using a predictable sequence and leaving the door open in a less obvious fashion.  All the bad guy needs is a reasonable probability of being able to predict the mask.  Zero mask is the degenerate case.  There are lots of ways to set a mask that isn't good enough.  Detecting insufficient randomness is harder and takes a lot more frames.

But that's only theory.  In practice, I think that your suggestion might work for your stated goal if deployed by enough server implementations.  It's probably not a bad "Security Considerations" point.

---

From: Greg Wilkins <[email-masked]>
Date: Fri, 4 Mar 2011 12:10:08 +1100

Jamie,

the same argument applies to why we should allow no masking and
remove the motivation to game the masking algorithm. By not allowing a
legitimate non-browser client to turn off masking in a well defined
standardised way, we will just encourage a proliferation of
implementations that will use zero, weak or copied keys.

Prohibition of a desire never works as a policy - it just creates an
uncontrolled black market.

cheers