[web-devel] questions about ResponseEnumerator

Gregory Collins greg at gregorycollins.net
Mon Oct 17 10:55:37 CEST 2011

On Mon, Oct 17, 2011 at 6:19 AM, Michael Snoyman <michael at snoyman.com> wrote:
> On Mon, Oct 17, 2011 at 5:16 AM, Kazu Yamamoto <kazu at iij.ad.jp> wrote:
>> But the following DOS is possible. A bad guy can open massive HTTP
>> connections to Warp and send partial bodies and keep the connections.
>> The connections will not time out. If the limit of open-file reaches,
>> Warp cannot accept a new connections from a good guy.
> I had not understood that this was the DOS attack you were trying to
> prevent, thank you for the clarification. I think you are correct that
> this is a problem, but perhaps we should solve it in the enumSocket
> function. If we tickle the timeout before calling Sock.recv and then
> pause it again afterwards, we will *only* be timing out on the part of
> the code that is receiving data from the client, as opposed to timing
> out on the application code itself.

This is called the "slow loris" attack. We spent a lot of effort in
Snap trying to guard against it. It isn't enough to simply tickle the
timeout when you get bytes from Sock.recv: the attacker can simply
send you one byte at a time, slowly, forever. There are different ways
to deal with this properly; in Snap we do a couple of things. For HTTP
file uploads, we use rate limiting to kill uploads that are running
slower than some user-defined threshold. (Our iteratee rate limiting
code is here: https://github.com/snapframework/snap-core/blob/master/src/Snap/Iteratee.hs#L709)

For HTTP requests, we use an absolute timeout which is never tickled
-- i.e., you have X seconds to get the HTTP status line and headers to
us -- so that the attacker can not simply trickle headers to us
forever. The output side, of course, the application has control over,
so we don't do anything special there.

Back to the issue of "no timeout" -- again, in general I think this is
a really bad idea, even for web services that are run in a trusted
environment. If no data is flowing across a connection, it's
impossible to distinguish "the other end died" from "it's just sitting
waiting patiently". Robust services that make long-lived connections
use ping packets to test connection liveness, period. Infinite network
timeouts, to me, are a synonym for "I didn't completely think through
the failure modes of this application".

Gregory Collins <greg at gregorycollins.net>

More information about the web-devel mailing list