MINOR: mux-h2: report glitches on early RST_STREAM

We leverage the SE_FL_APP_STARTED flag to detect whether the application
layer had a chance to run or not when an RST_STREAM is received. This
allows us to triage RST_STREAM between regular ones and harmful ones,
and to count glitches for them. It reveals extremely effective at
detecting fast HEADERS+RST pairs.

It could be useful to backport it to 3.2, though it depends on these
two previous patches to be backported first (the first one was already
planned and the second one is harmless, though will require to drop
the haterm changes):

  BUG/MINOR: stconn: Always declare the SC created from healthchecks as a back SC
  MINOR: stconn: flag the stream endpoint descriptor when the app has started
This commit is contained in:
Willy Tarreau 2026-03-19 18:00:20 +01:00
parent cf3173d92b
commit e375f1061a

View file

@ -3453,6 +3453,7 @@ static int h2c_handle_priority(struct h2c *h2c)
static int h2c_handle_rst_stream(struct h2c *h2c, struct h2s *h2s)
{
int rst_code;
int ret = 1;
TRACE_ENTER(H2_EV_RX_FRAME|H2_EV_RX_RST|H2_EV_RX_EOI, h2c->conn, h2s);
@ -3481,6 +3482,16 @@ static int h2c_handle_rst_stream(struct h2c *h2c, struct h2s *h2s)
if (h2s_sc(h2s)) {
se_fl_set_error(h2s->sd);
if (unlikely(!se_fl_test(h2s->sd, SE_FL_APP_STARTED))) {
/* the application layer has not yet started to read! */
TRACE_STATE("received early RST_STREAM", H2_EV_RX_FRAME|H2_EV_RX_RST, h2c->conn);
if (h2c_report_glitch(h2c, 1, "received early RST_STREAM, attack suspected")) {
TRACE_DEVEL("too many glitches, leaving on error", H2_EV_RX_FRAME|H2_EV_RX_RST, h2c->conn, h2s);
ret = 0; // report the error
}
}
se_report_term_evt(h2s->sd, se_tevt_type_rst_rcvd);
if (!h2s->sd->abort_info.info) {
h2s->sd->abort_info.info = (SE_ABRT_SRC_MUX_H2 << SE_ABRT_SRC_SHIFT);
@ -3491,7 +3502,7 @@ static int h2c_handle_rst_stream(struct h2c *h2c, struct h2s *h2s)
h2s->flags |= H2_SF_RST_RCVD;
TRACE_LEAVE(H2_EV_RX_FRAME|H2_EV_RX_RST|H2_EV_RX_EOI, h2c->conn, h2s);
return 1;
return ret;
}
/* processes a HEADERS frame. Returns h2s on success or NULL on missing data.