W3C home > Mailing lists > Public > ietf-http-wg@w3.org > July to September 2014

Re: Striving for Compromise (Consensus?)

From: Greg Wilkins <gregw@intalio.com>
Date: Sat, 12 Jul 2014 15:56:59 +1000
Message-ID: <CAH_y2NE_1pShP+ZXLEb_-=sXouhBmXtn_LT3FAFe8o0FvPmDzw@mail.gmail.com>
To: Roberto Peon <grmocg@gmail.com>
Cc: Amos Jeffries <squid3@treenet.co.nz>, HTTP Working Group <ietf-http-wg@w3.org>
Roberto,

So it sounds like you don't like continuations any more than the proposers
of "Greg et al".
So here is a path to something that will keep everybody happy,

Support the proposal - at some frame size >=18 <=31 bits. Then
continuations are gone and the two down sides for you are:

   1. Can't stream headers
   2. We advertise a max header size (it is a frame size but the same thing
   in proposal).

Now once we have that in place, we look at some new proposals to address
those concerns.

If we want to be able to stream headers, then we can put forward a proposal
to allow header frames to be fragmented in the same way data frames
currently are. ie we use the end-segment flag that they already carry to
indicate end of a header block.    Then the same framing layer code can be
used for fragmenting data and headers.      The discussion around that
proposal would also settle if they can be interleaved or not.   Hpack would
then be updated to work with whatever results (eg by removing reference set
or whatever else is necessary).

Once we say that headers can be fragmented, then a max header frame size
setting is a bit meaningless, so we can propose to drop that and just have
a single max frame size.      We can have the debate if there should be a
new setting of max header size (expressed as a uncompressed size) or not.

cheers













On 12 July 2014 15:17, Roberto Peon <grmocg@gmail.com> wrote:

>
>
>
> On Fri, Jul 11, 2014 at 9:40 PM, Amos Jeffries <squid3@treenet.co.nz>
> wrote:
>
>> On 12/07/2014 3:57 p.m., Roberto Peon wrote:
>> > In cases where HOL blocking is acceptable, you stream.
>> > This can be in cases where you know the entity that is sending the
>> headers
>> > you'd be streaming is trustworthy.
>> >
>> > If you don't want HOL blocking you don't stream.
>> > These don't conflict, they're simply different tradeoffs.
>> > -=R
>> >
>>
>> So let me ask you this:
>>  Why are you arguing so feircely against a proposal which sends up-front
>> the information to identify whether you need to make such a trust
>> decision in the first place?
>>
>
> That information, about the size of the header, is not trustworthy in a
> DoS scenario.
>
> If the information about the supposed size of the header is used to
> allocate buffers, it can create an asymmetric DoS scenario, where the
> attacker is spending much less resource than the server-side is spending.
> One accomplishes this by sending a large header size, and then either
> never fulfilling the promise of those bytes. Very little bandwidth gets
> wasted, and lots of memory gets consumed.
>
> The obvious work-around is to allocate buffers as they're consumed, which
> is essentially what would happen with header fragmentation.
>
> Another issue: Lets say that the server has an internal idea of the amount
> of memory it wishes to commit.
> It sees that the advertised header size is greater than it is willing to
> accept.
> It rejects it immediately. It has now leaked information to the attackers
> about the state of the server.
>
> And then there is the fact that we do have compression, and one can make
> promises till blue in the face about how much memory one is willing to
> accept compressed, and it has zero to do with the state commitment
> uncompressed if the server has to interpret the headers.
>
> So, the way I look at it, it offers no practical benefit while placing
> restrictions on proxies, tunnels and non-interpreting gateways w.r.t.
> buffering which induce latency and which increase state commitment even
> when they don't interpret. The bad outweighs the good.
>
>
>> Say you have an implementation that wants to stream. You arbitrarily
>> decide to send to your clients a fixed 32KB frame limit, and stream
>> anything under 20KB that comes back. When your clients send you new
>> HEADERS using Greg et al frames you get told whether it is 16KB, 256
>> bytes or 30KB in the frame intro. Make your decision before the first
>> byte of headers payload has been processed and take the
>> stream/non-stream code path to handle it.
>>  How does one do that with HEADERS+CONTNUATION? stream up to 16KB then
>> stall? *buffer* a "streamed" frame?
>>
>>
> Why would I set such a limit?
> I'd be better off setting a limit on the decompressed size, since that is
> more likely to correspond to what the server has to have resident in order
> to interpret it.
>
> Best case is ~compression-state-size + compressed frame size.
> Worst case is  ~compression-state-size * compressed_frame_size / 2
>
> Even then, why advertise it? It is better to consume the headers, and give
> the attackers no direct indication of the effect of the attack.
> -=R
>
>
>> The simplest solution to these and many other issues is what Greg et al
>> are proposing.
>>
>
>
>
>
>>
>> Amos
>>
>> >
>> > On Fri, Jul 11, 2014 at 8:33 PM, Amos Jeffries wrote:
>> >
>> >> On 12/07/2014 6:30 a.m., Martin Thomson wrote:
>> >>> On 11 July 2014 11:08, Willy Tarreau wrote:
>> >>>> I think that in Roberto's case, it's the opposite in fact. Assuming
>> he
>> >>>> runs a customer-facing gateway that aggregates streams to origin
>> servers
>> >>>> using less connections, *and* that he forwards headers on the fly
>> >> without
>> >>>> buffering, then a slow client sending a small header frame and slowly
>> >>>> pushing continuation frames would simply block all traffic from all
>> >> other
>> >>>> clients to that same server for the same connection.
>> >>>
>> >>> That's true.  So don't do that.
>> >>>
>> >>> Perhaps we are talking past each other.  Here's the matrix:
>> >>
>> >> Greg Wrote:
>> >>>
>> >>> 1) Increase frame size to 16-bits
>> >>> 1a) Add a settings for max_frame_size
>> >>> 2) Remove reference set from HPACK allowing for "streaming" decoding.
>> >>> 3) Requiring that all ":"-headers appear first.
>> >>> 4) Only allowing CONTINUATION if the previous frame is max_frame_size.
>> >>> 5) Allowing interleaving of CONTINUATION frames with other frames.
>> >>> 5b) The size of the HEADERS and CONTINUATION frames are removed from
>> the
>> >>> flow control window, but the they are never flow controlled.
>> >>>
>> >>>
>> >>>
>> >>
>> >>
>> >>>
>> >>> 0 can and do stream (1-3), no need for max_size frames (!4), no
>> >>> interleaving (!5)
>> >>>
>> >>>    - No state commitment DoS concern
>> >>>    - May spend extra cycles on framing
>> >>>    - May have HOL
>> >>>    - No stalling
>> >>>
>> >>> 1 can and do stream (1-3), need to fill frames before CONTINUATION
>> >>> (4), no interleaving (!5)
>> >>>
>> >>>    - No state commitment DoS concern
>> >>>    - No extra cycles on unnecessary framing
>> >>>    - May have HOL
>> >>>    - May stall
>> >>>
>> >>> 2 don't stream, no need for max_size frames (!4), no interleaving (!5)
>> >>>
>> >>>    - This is the status quo
>> >>
>> >> Strange that Roberto's argument for keeping status-quo was that we need
>> >> it to stream headers. But you summarize status-quo under "don't
>> stream".
>> >> I find that case (0) above is closer to status-quo.
>> >>
>> >>>    - No state commitment DoS concern
>> >>>    - May spend extra cycles on framing
>> >>>    - May have HOL
>> >>>    - No stalling
>> >>>
>> >>> 3 don't stream, need to fill frames before CONTINUATION (4), no
>> >>> interleaving (!5)
>> >>>
>> >>>    - No state commitment DoS concern
>> >>>    - No extra cycles on unnecessary framing
>> >>>    - May have HOL
>> >>>    - May stall
>> >>>
>> >>> 4 can and do stream (1-3), no need for max_size frames (!4),
>> >> interleaving (5)
>> >>>
>> >>>    - No state commitment DoS concern
>> >>>    - May spend extra cycles on framing
>> >>>    - Can avoid HOL
>> >>>    - May stall
>> >>>
>> >>>
>> >>> 5 can and do stream (1-3), need to fill frames before CONTINUATION
>> >>> (4), interleaving (5)
>> >>>
>> >>>    - State commitment DoS concern
>> >>>    - No extra cycles on unnecessary framing
>> >>>    - No HOL
>> >>>    - May stall
>> >>>    - Streaming not possible where max_size doesn't match up
>> >>>
>> >>> 6 don't stream, no need for max_size frames (!4), interleaving (5)
>> >>>
>> >>>    - State commitment DoS concern
>> >>>    - May spend extra cycles on framing
>> >>>    - Can avoid HOL
>> >>>    - No stalling
>> >>>
>> >>> 7 don't stream, need to fill frames before CONTINUATION (4),
>> >> interleaving (5)
>> >>>
>> >>>    - State commitment DoS concern
>> >>>    - No extra cycles on unnecessary framing
>> >>>    - Can avoid HOL
>> >>>    - May stall
>> >>>
>> >>> I think that's good enough for our purposes.
>> >>>
>> >>> Given that my priority order here is approximately: state commitment >
>> >>> stalling > HOL > CPU, I think that status quo is looking pretty good.
>> >>>
>> >>> Note that option 5, which is the complete combination of all proposed
>> >>> changes, seems to actually be the worst in this analysis.
>> >>>
>> >>
>> >>
>> >> Matrix case (2) has more in common with "Greg et al" large frames
>> >> proposal than status-quo h2-13.
>> >>  * dont stream (large frames requests buffering on sender)
>> >>  * no need for max_size frames (large frames sends frame size matching
>> >> payload)
>> >>  * no interleaving (Greg et al large frames does not permit even
>> >> mistaken implementers to accidentally interleave frames inside each
>> >> others payload)
>> >>
>> >> Greg et al proposal causes the '-' bullets to change thusly:
>> >>
>> >>  - "No state commitment DoS concern" - Greg et al frame limit removes
>> >> implementations protocol mandated commitment to handle infinite-length
>> >> CONTINUATION payload. Greatlyimproving this over the status-quo.
>> >>
>> >>  - "May spend extra cycles on framing" - Greg et al frames remove this
>> >> issue completely.
>> >>
>> >>  - "May have HOL" - no change here, but Greg et al frames permit
>> senders
>> >> to mediate frame size and prevent HOL blocking on outgoing connections.
>> >> status-quo actually mandates buffering "state commitment DoS concern"
>> as
>> >> the only possible way to resolve HOL blocking.
>> >>
>> >>  - "No stalling" - stalling is *always* possible with frames overhead
>> >> about 3 bytes. It is a TCP behaviour. h2 has frame overhead 8-12 bytes.
>> >>
>> >>
>> >>
>> >> As for your priority order:
>> >>
>> >>> Given that my priority order here is approximately:
>> >>
>> >>> state commitment >
>> >>
>> >> Greg et al. large frames leave the state commitmet equal to status quo
>> >> unless implementer decides otherwise. Implemeter may advertise *less*
>> >> state commitment than h2 specification default.
>> >>
>> >>> stalling
>> >>
>> >> Stalling is possible in all circumstances where more than two bytes
>> need
>> >> to be strung together. status quo is *very bad* in encouraging this, as
>> >> are the interleaving and fragmentation proposals.
>> >>
>> >> Greg et al large frames require the sender to accumulate the frame
>> >> before delivery to ensure length is accurate. This actively closes many
>> >> paths and potential HTTP/2 implementation mistakes leading to stalling.
>> >> The remaining causes are all TCP induced and need to be resolved at the
>> >> TCP layer.
>> >>
>> >>> HOL
>> >>
>> >> Only occurs with status quo and proposals involving CONTINUATION or
>> >> fragments.
>> >> Greg et al large frames constrains senders not to send at all unless
>> the
>> >> frame is fully available and can be delivered.
>> >>
>> >>
>> >>> CPU, I think that status quo is looking pretty good.
>> >>
>> >> I think that Greg et al frames proposal still looks better.
>> >>
>> >> Amos
>> >>
>> >>
>> >
>>
>>
>


-- 
Greg Wilkins <gregw@intalio.com>
http://eclipse.org/jetty HTTP, SPDY, Websocket server and client that scales
http://www.webtide.com  advice and support for jetty and cometd.
Received on Saturday, 12 July 2014 05:57:28 UTC

This archive was generated by hypermail 2.3.1 : Wednesday, 30 March 2016 09:57:09 UTC