Re: Stream State and PRIORITY Frames

Amos Jeffries <squid3@treenet.co.nz> Thu, 19 January 2017 09:05 UTC

Return-Path: <ietf-http-wg-request+bounce-httpbisa-archive-bis2juki=lists.ie@listhub.w3.org>
X-Original-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Delivered-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id CD4D7128B38 for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Thu, 19 Jan 2017 01:05:18 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -10.12
X-Spam-Level:
X-Spam-Status: No, score=-10.12 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-3.199, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 8iddu3WG7tc1 for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Thu, 19 Jan 2017 01:05:15 -0800 (PST)
Received: from frink.w3.org (frink.w3.org [128.30.52.56]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 80BD1127ABE for <httpbisa-archive-bis2Juki@lists.ietf.org>; Thu, 19 Jan 2017 01:05:15 -0800 (PST)
Received: from lists by frink.w3.org with local (Exim 4.80) (envelope-from <ietf-http-wg-request@listhub.w3.org>) id 1cU8b6-0000xK-0u for ietf-http-wg-dist@listhub.w3.org; Thu, 19 Jan 2017 09:01:32 +0000
Resent-Date: Thu, 19 Jan 2017 09:01:32 +0000
Resent-Message-Id: <E1cU8b6-0000xK-0u@frink.w3.org>
Received: from titan.w3.org ([128.30.52.76]) by frink.w3.org with esmtps (TLS1.2:RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from <squid3@treenet.co.nz>) id 1cU8b1-0000wU-Jf for ietf-http-wg@listhub.w3.org; Thu, 19 Jan 2017 09:01:27 +0000
Received: from [121.99.228.82] (helo=treenet.co.nz) by titan.w3.org with esmtp (Exim 4.84_2) (envelope-from <squid3@treenet.co.nz>) id 1cU8ap-00085r-Ts for ietf-http-wg@w3.org; Thu, 19 Jan 2017 09:01:22 +0000
Received: from [192.168.20.251] (unknown [121.98.40.15]) by treenet.co.nz (Postfix) with ESMTP id 67289E6EE5 for <ietf-http-wg@w3.org>; Thu, 19 Jan 2017 22:00:42 +1300 (NZDT)
To: ietf-http-wg@w3.org
References: <CAFn2buAYWHQSWhhoKZ2GKbqXR1A+tScjkAwZmOuQ9gV9jMp2bA@mail.gmail.com> <CAGZNdJWe0Y=M_SWmgYabKbWZwPEuJdw67Km8+UtR4oUtZuXA5A@mail.gmail.com> <2BC01E49-91A1-43A7-AFD0-5A34F2689428@lukasa.co.uk> <CAFn2buDCMwMp=rR0C_yt4-gUwyFhY6ruonz9wT-jVMu+Kir=nA@mail.gmail.com> <C51C3F51-37BE-489F-BA1D-76B101517307@lukasa.co.uk> <CAFn2buAE-EdTEG9x-wLQSy5Osmcq1Hdps9YLW_7j9CTV4_Fuyw@mail.gmail.com> <CANatvzzEV6Qd1huVxO=T2m7UwwX207RCetrXyZ1FMMGrBtzeEg@mail.gmail.com>
From: Amos Jeffries <squid3@treenet.co.nz>
Message-ID: <e420eda0-57fc-43e8-a82a-0988db75ab32@treenet.co.nz>
Date: Thu, 19 Jan 2017 22:00:25 +1300
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0
MIME-Version: 1.0
In-Reply-To: <CANatvzzEV6Qd1huVxO=T2m7UwwX207RCetrXyZ1FMMGrBtzeEg@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit
Received-SPF: pass client-ip=121.99.228.82; envelope-from=squid3@treenet.co.nz; helo=treenet.co.nz
X-W3C-Hub-Spam-Status: No, score=-4.3
X-W3C-Hub-Spam-Report: AWL=-1.172, BAYES_00=-1.9, RDNS_NONE=0.793, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, W3C_AA=-1, W3C_WL=-1
X-W3C-Scan-Sig: titan.w3.org 1cU8ap-00085r-Ts 1a48d64644b91274322307388a44699a
X-Original-To: ietf-http-wg@w3.org
Subject: Re: Stream State and PRIORITY Frames
Archived-At: <http://www.w3.org/mid/e420eda0-57fc-43e8-a82a-0988db75ab32@treenet.co.nz>
Resent-From: ietf-http-wg@w3.org
X-Mailing-List: <ietf-http-wg@w3.org> archive/latest/33322
X-Loop: ietf-http-wg@w3.org
Resent-Sender: ietf-http-wg-request@w3.org
Precedence: list
List-Id: <ietf-http-wg.w3.org>
List-Help: <http://www.w3.org/Mail/>
List-Post: <mailto:ietf-http-wg@w3.org>
List-Unsubscribe: <mailto:ietf-http-wg-request@w3.org?subject=unsubscribe>

On 19/01/2017 3:57 p.m., Kazuho Oku wrote:
> 2017-01-19 9:53 GMT+09:00 Scott Mitchell <scott.k.mitch1@gmail.com>:
>>
>>
>> On Wed, Jan 18, 2017 at 11:50 AM, Cory Benfield <cory@lukasa.co.uk> wrote:
>>>
>>>
>>> On 18 Jan 2017, at 16:38, Scott Mitchell <scott.k.mitch1@gmail.com> wrote:
>>>
>>> This is interesting. If FF is using streams 1-7 then as soon as stream 9
>>> is used for a HEADERS request that will close streams 1-7 according to
>>> section 5.1.1:
>>>
>>>> first use of a new stream identifier implicitly closes all streams in
>>>> the "idle" state that might have been initiated by that peer with a
>>>> lower-valued stream identifier
>>>
>>>
>>> Only if they are not opened via HEADERS frames, which they are. FF sent (I
>>> haven’t checked recently) PRIORITY frames for the first few stream IDs, and
>>> then started sending HEADERS from 1 onwards.
>>>
>>>
>>
>>
>> I just ran FF 50.1.0 against a simple local server (TLS+ALPN) and here is
>> the behavior I observe:
>>
>> 1. Client PRIORITY [StreamId=3,StreamDependency=0,
>> Weight=201,Exclusive=False] -> Server
>> 2. Client PRIORITY [StreamId=5,StreamDependency=0,
>> Weight=101,Exclusive=False] -> Server
>> 3. Client PRIORITY [StreamId=7,StreamDependency=0, Weight=1,Exclusive=False]
>> -> Server
>> 4. Client PRIORITY [StreamId=9,StreamDependency=7, Weight=1,Exclusive=False]
>> -> Server
>> 5. Client PRIORITY [StreamId=11,StreamDependency=3,
>> Weight=1,Exclusive=False] -> Server
>> 6. Client HEADERS [StreamId=13,StreamDependency=11,
>> Weight=2,Exclusive=False] -> Server (a GET "/" request)
>> 7. Client HEADERS [StreamId=15,StreamDependency=0,
>> Weight=16,Exclusive=False] -> Server (a GET "/favicon.ico" request)
>>
>> There were other frames (SETTINGS, DATA, PING, WINDOW_UPDATE, GO_AWAY) which
>> were omitted for the purposes of this discussion.
>>
>> Based on the RFC it seems like stream ids {3, 5, 7, 11} should be closed at
>> step (6).
> 
> I had the same discussion with Cory, and now I agree with him that we
> should _not_ interpret the specification that way.
> 

IIRC the intention behind the closing behaviour for idle streams was to
ensure that we could optimize away the need to maintain a list or array
of 2^31 state entries.

Omitting PRIORITY from the MAX_STREAMS voids that benefit.


> As Cory points out on
> https://github.com/h2o/h2o/pull/1136#issuecomment-266213322, the
> normative definition is
> 
>    The identifier of a newly established stream MUST be numerically
>    greater than all streams that the initiating endpoint has opened or
>    reserved. This governs streams that are opened using a HEADERS frame
>    and streams that are reserved using PUSH_PROMISE.
> 
> Therefore, a PRIORITY frame does not implicitly close the streams with
> smaller IDs.
> 
> The following text that discusses when a stream gets implicitly closed
> is written immediately after the formal description show above, so it
> is fair to assume that the word _use_ in the sentence means when the
> stream is opened or reserved (and not when a PRIORITY frame is
> received).
> 
>    The first use of a new stream identifier implicitly closes all
>    streams in the "idle" state that might have been initiated by that
>    peer with a lower-valued stream identifier.
> 
> 
>> Note that FF is not doing anything wrong here. It shouldn't have
>> to care that the streams are CLOSED in this scenario (assuming these streams
>> only ever have PRIORITY frames exchanged).

It is causing state to be allocated on the server and on every
intermediary along the way which accepts it.

Consider the effects of 2^31 PRIORITY frames being sent with different
IDs before the first HEADERS is used.
 Notice how even this one case is markedly worse than sending just one
HEADERS with stream ID == 2^31 to waste server sockets.

Add some other factors:
 * repeated frames are extremely cheap for sender.
 * random order on the frames.
 * encoding data in the sequence of stream-ids.
 * variance in the frequency of delay between frames.

One suddenly finds there is a whole category (or three) of attacks
available unless PRIORITY on an idle stream is drop/ignored (at worst)
or GOAWAY (at best).


> It would be interesting to get a
>> FF dev to comment on the expected stream state here just to be sure these
>> streams will only be used for PRIORITY. Either way maintaining/interpreting
>> the priority is at the discretion of the server and these streams being
>> closed does not impact the server's ability to do this (as discussed
>> previously the RFC suggests retaining priority for closed streams).

see above. Any server which does accept is opening itself to a world of
problems with complex workarounds. Allocating state for them makes it
even worse.

What I'd like from Firefox is an explanation of why exactly PRIORITY is
the first thing(s) happening here at all?

What exactly does it mean for them to set PRIORITY on a non-existent stream?


Amos