Here we consider that if a HEADERS frame is made of more than 4 fragments
whose average size is lower than 1kB, that's very likely an abuse so we
count a glitch per 16 fragments, which means 1 glitch per 1kB frame in a
16kB buffer. This means that an abuser sending 1600 1-byte frames would
increase the counter by 100, and that sending 100 headers per request in
individual frames each results in a count of ~7 to be added per request.
A test consisting in sending 100M requests made of 101 frames each over
a connection resulted in ~695M glitches to be counted for this connection.
Note that no special care is taken to avoid wrapping since it already takes
a very long time to reach 100M and there's no particular impact of wrapping
here (roughly 1M/s).
struct buffer *copy = NULL;
unsigned int msgf;
struct htx *htx = NULL;
- int flen; // header frame len
+ int flen = 0; // header frame len
+ int fragments = 0;
int hole = 0;
int ret = 0;
int outlen;
hole += h2c->dpl + 9;
h2c->dpl = 0;
TRACE_STATE("waiting for next continuation frame", H2_EV_RX_FRAME|H2_EV_RX_FHDR|H2_EV_RX_CONT|H2_EV_RX_HDR, h2c->conn);
+ fragments++;
goto next_frame;
}
htx_to_buf(htx, rxbuf);
free_trash_chunk(copy);
TRACE_LEAVE(H2_EV_RX_FRAME|H2_EV_RX_HDR, h2c->conn);
+
+ /* Check for abuse of CONTINUATION: more than 4 fragments and less than
+ * 1kB per fragment is clearly unusual and suspicious enough to count
+ * one glitch per 1kB fragment in a 16kB buffer, which means that an
+ * abuser sending 1600 1-byte frames in a 16kB buffer would increment
+ * its counter by 100.
+ */
+ if (unlikely(fragments > 4) && fragments > flen / 1024 && ret != 0)
+ h2c->glitches += (fragments + 15) / 16;
+
return ret;
fail: