Subject: [hybi] Websocket over TLS keep-alive overhead

From: <[email-masked]>
Date: Fri, 23 Nov 2012 10:59:23 +0000

Hi,

I have been trying to check the size of WebSocket "keep-alive" messages over TLS/TCP. By "keep-alive" I mean messages that are sent just to keep the TCP connection alive through NATs, firewalls etc. I guess there are two ways of doing that in WebSocket. Either use the PING - PONG control frames or send an actual small data frame over the connection. In either case the plaintext payload is small, around 6-7 bytes with the WebSocket header and masking key. 

The question is how big such messages are when sent over TLS. I've done some traces with http://www.websocket.org/echo.html and it seems 74(!) byte payloads get generated by just sending a single character over the WS/TLS/TCP connection, using Chrome. If I'm reading the Wireshark dissector output correctly, there are two TLS records inside the TCP packet, each with size 5 + 32 bytes (32 = 16 byte minimum block + 16 byte MAC?). That's fine except I don't understand why two TLS records are needed. This might be a single instance but I've also gotten traces of two XMPP clients that send 2-byte CRLF as keep-alive, and that also becomes the same 74 bytes over TLS. (In the XMPP cases I believe TLS compression is in use, don't know about the Chrome - websocket.org connection.)

74 bytes + TCP/IP headers is still a very small packet, but it may become an issue in WCDMA/HSPA 3G networks. In those networks very small amounts of data can be carried on a low power-consuming radio channel (FACH), while any larger traffic triggers a more-consuming dedicated channel (DCH) to be activated. So, there is a significant difference in power consumption which way the keep-alive happens - considering you do it every 5 minutes for several hours, for instance. 74 bytes + TCP/IP happen to be just about on the border, so depending on the network settings and the phase of the moon it sometimes triggers DCH. Something like 50 bytes in TCP payload seems to be already safe in this sense, unless you do it like once a minute or faster.

Any insight on this? What is the KA size supposed to be and what might explain these 74 byte messages I'm seeing? Any way to make it "smaller"?

Markus

---

From: Tobias Oberstein <[email-masked]>
Date: Fri, 23 Nov 2012 04:00:46 -0800

> The question is how big such messages are when sent over TLS. I've done some
> traces with http://www.websocket.org/echo.html and it seems 74(!) byte
> payloads get generated by just sending a single character over the WS/TLS/TCP
> connection, using Chrome. If I'm reading the Wireshark dissector output
> correctly, there are two TLS records inside the TCP packet, each with size 5 +
> 32 bytes (32 = 16 byte minimum block + 16 byte MAC?). That's fine except I
> don't understand why two TLS records are needed. This might be a single

Here is a wild guess: sending a single octet from within JS/Chrome might
call into the TLS implementation on the Chrome/client side 2 times:
a) for the WS frame header, b) for the payload. This might generate 2 TLS
records.

WS Pings cannot be triggered from JS, but browsers of course respond to
server-sent WS Pings with a Pong, you could try the following experiment
and do wiretapping:

On a WS TLS connection, send WS Pings from server (with no payload,
unmasked = 2 octets) and see if the Pong responses (no payload,
masked = 6 octets) get assembled into 1 or 2 TLS records ..

-- Tobias

---

From: Takeshi Yoshino <[email-masked]>
Date: Thu, 29 Nov 2012 15:22:45 +0900

Hi,

Chromium is using 1/n-1 record splitting for TLS 1.0 connection w/ CBC mode
cipher to work around BEAST exploit. So, even a WebSocket frame with 1
octet payload (client -> server, 7 octets in total. AES block size (16) * 2
- SHA1 HMAC size (20) - padding length field size (1) > 7, so 1 application
data record with 32 octets payload is enough) will be packed into two TLS
records with big padding.

re: TLS compression, it's disabled on Chromium to address another exploit
called CRIME.

Thanks
Takeshi

---

From: Jamie Lokier <[email-masked]>
Date: Thu, 29 Nov 2012 10:11:02 +0000

Takeshi Yoshino wrote:
>    Hi,
>    Chromium is using 1/n-1 record splitting for TLS 1.0 connection w/ CBC
>    mode cipher to work around BEAST exploit. So, even a WebSocket frame
>    with 1 octet payload (client -> server, 7 octets in total. AES block
>    size (16) * 2 - SHA1 HMAC size (20) - padding length field size (1) >
>    7, so 1 application data record with 32 octets payload is enough) will
>    be packed into two TLS records with big padding.
>    re: TLS compression, it's disabled on Chromium to address another
>    exploit called CRIME.

It might make sense if TLS could transmit its own, much shorter,
keepalive messages, which are for the sole purpose of keeping the link
alive.  I would guess, since they have no other effect, that they
wouldn't be exploitable in the same way.  Is that right?

It would be best if they could be invoked from the higher layer rather
than generated in TLS itself (because the higher layer will have a
better idea of the keepalive patterns that it needs), and if they were
one-way keepalives rather than PING/PONG to avoid amplification
attacks, and because PING/PONG is not the most efficient keepalive
pattern.

Is there provision in TLS for that sort of thing now?

(Of course over mobile links, it would make much more sense for power
efficiency to have a single, aggregated keepalive stream for all
sockets rather than one per active websocket, or some other way of
taking advantage of the phone's existing mobile link-level keepalives
which it already does and are designed for efficiency.)

-- Jamie

---

From: Roberto Peon <[email-masked]>
Date: Thu, 29 Nov 2012 10:42:45 -0800

++
On Nov 29, 2012 2:11 AM, "Jamie Lokier" <[email-masked]> wrote:

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