Re: [hybi] Handshake was: The WebSocket protocol issues.

Willy Tarreau <w@1wt.eu> Tue, 12 October 2010 05:10 UTC

Return-Path: <w@1wt.eu>
X-Original-To: hybi@core3.amsl.com
Delivered-To: hybi@core3.amsl.com
Received: from localhost (localhost [127.0.0.1]) by core3.amsl.com (Postfix) with ESMTP id 95A7A3A68AE for <hybi@core3.amsl.com>; Mon, 11 Oct 2010 22:10:51 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.773
X-Spam-Level:
X-Spam-Status: No, score=-2.773 tagged_above=-999 required=5 tests=[AWL=-0.730, BAYES_00=-2.599, HELO_IS_SMALL6=0.556]
Received: from mail.ietf.org ([64.170.98.32]) by localhost (core3.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HgMn+DbfW0Fw for <hybi@core3.amsl.com>; Mon, 11 Oct 2010 22:10:50 -0700 (PDT)
Received: from 1wt.eu (1wt.eu [62.212.114.60]) by core3.amsl.com (Postfix) with ESMTP id DDB503A68AF for <hybi@ietf.org>; Mon, 11 Oct 2010 22:10:49 -0700 (PDT)
Received: (from willy@localhost) by mail.home.local (8.14.4/8.14.4/Submit) id o9C5BvoF019069; Tue, 12 Oct 2010 07:11:57 +0200
Date: Tue, 12 Oct 2010 07:11:57 +0200
From: Willy Tarreau <w@1wt.eu>
To: Eric Rescorla <ekr@rtfm.com>
Message-ID: <20101012051157.GG17225@1wt.eu>
References: <4CAFB9C4.6030905@caucho.com> <AANLkTinv5Ym5jwUEqS76z3UkVa7GpmOBT_WXhBbFK0-m@mail.gmail.com> <20101009055723.GL4712@1wt.eu> <AANLkTimY2DjxgZybibSRtc7L34Wns2KhQC=Wa9K6PYku@mail.gmail.com> <20101009204009.GP4712@1wt.eu> <AANLkTi=Az0RmE1Uipo068zMh3YzgMpM2tQ+zYxaDT47A@mail.gmail.com> <20101011053354.GA12672@1wt.eu> <AANLkTimC6A+5ZWuNhWASehAibUB9fQKVCPVsVpShUkrW@mail.gmail.com> <20101011204228.GB17225@1wt.eu> <AANLkTik=aBGxjnzwkVF=1p0Fmyj0WDF-gjFuqwpyyrTz@mail.gmail.com>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
In-Reply-To: <AANLkTik=aBGxjnzwkVF=1p0Fmyj0WDF-gjFuqwpyyrTz@mail.gmail.com>
User-Agent: Mutt/1.4.2.3i
Cc: hybi <hybi@ietf.org>, Bjoern Hoehrmann <derhoermi@gmx.net>
Subject: Re: [hybi] Handshake was: The WebSocket protocol issues.
X-BeenThere: hybi@ietf.org
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: Server-Initiated HTTP <hybi.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/listinfo/hybi>, <mailto:hybi-request@ietf.org?subject=unsubscribe>
List-Archive: <http://www.ietf.org/mail-archive/web/hybi>
List-Post: <mailto:hybi@ietf.org>
List-Help: <mailto:hybi-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/hybi>, <mailto:hybi-request@ietf.org?subject=subscribe>
X-List-Received-Date: Tue, 12 Oct 2010 05:10:51 -0000

On Mon, Oct 11, 2010 at 03:22:38PM -0700, Eric Rescorla wrote:
> > Yes they do for components which rely on the close only and don't require
> > any content-length (eg: most monitoring tools). If the server did not care
> > about the close in the request and waited for a second request instead of
> > closing, the client would wait for the server to close to determine the
> > end of the response, which is after the keep-alive timeout of the server.
> 
> 
> I don't see how this makes sense. Regardless of the setting of Connection:
> close
> if the server is not going to either put a length field or chunked encoding,
> it
> needs to close the connection at the end of the response. Timeouts don't
> enter into it.

I'm not saying that the server is not going to put a length, but that the
client is not going to make use of it because it's either an old one or a
simple one. All clients that rely on "Connection: close" are free to ignore
content-length, and that's sometimes for this exact reason that they add
this header.

In short you would have this if the server ignored "Connection: close" :

Req> GET /server-status HTTP/1.1
Req> Host: localhost
Req> Connection: close

Res> HTTP/1.1 200 OK
Res> Content-length: 3
Res>
Res> OK

And now the server waits for the client to send a new request, while the
client waits for the server to close.

> I don't know what you mean by "monitoring tools" here...

All simple tools that you find everywhere in prod environments to ensure
the service is OK. Scripts can either make use of the very common netcat
utility, of any home-made TCP client or even make use of the shell like
this :

#!/bin/bash
ip=$1; port=$2
exec 3</dev/tcp/$ip/$port
printf "GET /server-status HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n" >&3
read -t 3 -u 3 ; set -- $REPLY; status=$2
(date;echo "$1:$2: $status";echo;
 while read -t 3 -u 3; do
    echo $REPLY
 done
) >> log.$ip.$port

(...)
> > While it's recommended for
> > other connections, we still see some servers that don't advertise a content
> > length for HTTP/1.0 request (even Tomcat until very recently).
> 
> 
> I don't understand what point you're making here. It's entirely possible for
> a
> server to be interoperable while ignoring Connection: close simply by always
> using a length field/chunked encoding and using a timeout. This leads to
> neither
> deadlock nor interop problems. If you think there is an interop problem
> here,
> please describe the sequence of events that causes it.

Precisely as explained above, the client generally sets "Connection: close"
to indicate that it can only rely on the close and will probably not care
about the Content-length header. Emitting/parsing content-length is not a
requirement if you don't intend to use a persistent connection. Most
versions of tomcat (even recent ones) made use of that asumption to avoid
sending the content-length and transfer encoding when they saw "Connection:
close".

> If not, then I don't
> see
> how you can rely on proper Connection: close behavior as a security feature.

It's not a matter of a security feature, it's that "Connection: close" has a
strong enough semantics which means "terminate this request with a close as
you did in the old days, I won't parse your length headers anyway". So if the
connection is closed after processing the first request, you won't be using
the connection to send a second request.

(...)
> Who said anything about "massive attacks"? That's not my concern. My concern
> is deploying a new feature which makes otherwise secure systems insecure.

OK, so basically we're looking for a shared hosting environment that offers
low-cost accounts to various people with PHP scripting, who does not know
about "Connection: close", who does not know that CONNECT+200 is a tunnel,
and if we find such a hosting provider, we should make sure that the handshake
cannot be abused by one of their customer to send a request to another of
their customers... Do you seriously think that such a broken provider's
security only relies on a complex WS handshake ? I'd guess that given that
we manage to find *one*, it would have other serious issues such as HTTP
request smuggling and things like this.

> > > Yes, that's why using CONNECT is a desirable feature, since for
> > > interoperability
> > > reasons servers/proxies cannot treat data that appears in the tunnel as
> > if
> > > it were HTTP traffic.
> >
> > And that's also why there cannot be a second request after the 200.
> 
> 
> Yes, that's my point. That you can't really have an interoperable CONNECT
> implementation at all without ignoring everything after the 200.

I agree with that, and that's one of the reasons I proposed CONNECT too
some months ago.

> By contrast,
> you can have an interoperable implementation while ignoring Connection:
> close.
> This is why I feel more comfortable relying on the CONNECT behavior than
> on Connection: close.

I understand your point given the wording in the spec even if from
experience I don't agree.

> > > Yes, I agree that this would be required. I don't agree that it's a
> > > dealbreaker.
> >
> > Well, first it's not compatible with any existing infrastructure, which is
> > a bit limited outside of the lab.
> 
> Yes, I agree it requires an infrastructure change. I don't agree that it's a
> dealbreaker.

Here I don't agree. WS was supposed to make use of existing infrastructure.

> > Second, it means that the front server
> > would first have to acknowledge a WS handshake on behalf of any possible
> > server behind it and finally have to return in WS frames a "Sorry man, I
> > thought I could hand that connection to someone but there's nobody where
> > you want to go".
> 
> 
> No, this is not correct. The server can process the entire handshake,
> including
> the encrypted destination portion, and then only after that respond to the
> request.
> This requires, as Adam suggested, having the initial "Host" block encrypted
> with a key supplied only by the client.

Then there's something I did not understand, because from what I understood
of his proposal, the Host was supposed to be sent after the handshake so
that the handshake contains nothing that can be controlled by the user.
BTW, I don't even agree with that goal, because if we want to be compatible
with HTTP, we can make use of the regular HTTP headers without any worries.
Whether the browser fills a Host header in a WS request or in an HTTP request
makes no difference. It will just fill it correctly. Even cookies work fine.
There's no need for encryption there. Let's just respect standard HTTP.

I agree about having an invalid host name in the CONNECT request though, in
order to avoid possible forwarding on real proxies. But let's have the Host
header hold the real information in clear text.

Regards,
Willy