]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-h2: count excess of CONTINUATION frames as a glitch
authorWilly Tarreau <w@1wt.eu>
Fri, 19 Jan 2024 17:20:21 +0000 (18:20 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 8 Feb 2024 14:51:49 +0000 (15:51 +0100)
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).

src/mux_h2.c

index 6b9ca4b71f078c868b71d527c50a01fd97e9ec6d..19aecf352c040d228349b1e760ceaf2c56eb49ec 100644 (file)
@@ -5128,7 +5128,8 @@ static int h2c_dec_hdrs(struct h2c *h2c, struct buffer *rxbuf, uint32_t *flags,
        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;
@@ -5203,6 +5204,7 @@ next_frame:
                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;
        }
 
@@ -5391,6 +5393,16 @@ 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: