[6.0] 7c3fac93c H2: Check rapid reset whenever we send a RST frame for a stream

Martin Blix Grydeland martin at varnish-software.com
Wed Aug 13 12:03:06 UTC 2025


commit 7c3fac93c39260873b87f69b6178e73abb42be6b
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date:   Tue Jul 1 15:50:10 2025 +0200

    H2: Check rapid reset whenever we send a RST frame for a stream
    
    This checks and charges the rapid reset budget whenever we send a RST
    frame, causing a session error if the budget is exhausted.
    
    This fixes the reverse rapid reset vulnerability.

diff --git a/bin/varnishd/http2/cache_http2_send.c b/bin/varnishd/http2/cache_http2_send.c
index 520f3e5eb..51f5f0de8 100644
--- a/bin/varnishd/http2/cache_http2_send.c
+++ b/bin/varnishd/http2/cache_http2_send.c
@@ -419,6 +419,7 @@ H2_Send_RST(struct worker *wrk, struct h2_sess *h2, const struct h2_req *r2,
     uint32_t stream, h2_error h2e)
 {
 	char b[4];
+	h2_error h2e_rr = NULL;
 
 	CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
 	CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
@@ -431,6 +432,11 @@ H2_Send_RST(struct worker *wrk, struct h2_sess *h2, const struct h2_req *r2,
 	vbe32enc(b, h2e->val);
 
 	H2_Send_Frame(wrk, h2, H2_F_RST_STREAM, 0, sizeof b, stream, b);
+
+	if (h2_rapid_reset_check(wrk, h2, r2))
+		h2e_rr = h2_rapid_reset_charge(wrk, h2, r2);
+	if (h2e_rr != NULL)
+		h2->error = h2e_rr;
 }
 
 void
diff --git a/bin/varnishtest/tests/f00017.vtc b/bin/varnishtest/tests/f00017.vtc
new file mode 100644
index 000000000..6370652be
--- /dev/null
+++ b/bin/varnishtest/tests/f00017.vtc
@@ -0,0 +1,63 @@
+varnishtest "h2 reverse rapid reset"
+
+barrier b1 sock 2 -cyclic
+barrier b2 sock 5 -cyclic
+
+server s1 {
+	rxreq
+	txresp
+} -start
+
+varnish v1 -cliok "param.set feature +http2"
+varnish v1 -cliok "param.set debug +syncvsl"
+varnish v1 -cliok "param.set h2_rapid_reset_limit 3"
+varnish v1 -cliok "param.set h2_rapid_reset 5"
+
+varnish v1 -vcl+backend {
+	import vtc;
+
+	sub vcl_recv {
+		if (req.http.barrier) {
+			vtc.barrier_sync(req.http.barrier);
+		}
+		vtc.barrier_sync("${b2_sock}");
+	}
+
+} -start
+
+client c1 {
+	stream 0 {
+		rxgoaway
+		expect goaway.err == ENHANCE_YOUR_CALM
+	} -start
+
+	stream 1 {
+		txreq -hdr barrier ${b1_sock}
+		barrier b1 sync
+		txwinup -size 0
+		rxrst
+	} -run
+	stream 3 {
+		txreq -hdr barrier ${b1_sock}
+		barrier b1 sync
+		txwinup -size 0
+		rxrst
+	} -run
+	stream 5 {
+		txreq -hdr barrier ${b1_sock}
+		barrier b1 sync
+		txwinup -size 0
+		rxrst
+	} -run
+	stream 7 {
+		txreq -hdr barrier ${b1_sock}
+		barrier b1 sync
+		txwinup -size 0
+		rxrst
+	} -run
+
+	barrier b2 sync
+	stream 0 -wait
+} -run
+
+varnish v1 -expect sc_rapid_reset == 1


More information about the varnish-commit mailing list