Mercurial > hg > nginx
diff src/http/v3/ngx_http_v3_streams.c @ 8881:72b304f6207c quic
HTTP/3: traffic-based flood detection.
With this patch, all traffic over HTTP/3 bidi and uni streams is counted in
the h3c->total_bytes field, and payload traffic is counted in the
h3c->payload_bytes field. As long as total traffic is many times larger than
payload traffic, we consider this to be a flood.
Request header traffic is counted as if all fields are literal. Response
header traffic is counted as is.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Thu, 07 Oct 2021 13:22:42 +0300 |
parents | 531075860fe2 |
children | 925572184d4a |
line wrap: on
line diff
--- a/src/http/v3/ngx_http_v3_streams.c Wed Oct 06 14:51:16 2021 +0300 +++ b/src/http/v3/ngx_http_v3_streams.c Thu Oct 07 13:22:42 2021 +0300 @@ -171,6 +171,7 @@ ngx_buf_t b; ngx_int_t rc; ngx_connection_t *c; + ngx_http_v3_session_t *h3c; ngx_http_v3_uni_stream_t *us; c = rev->data; @@ -207,6 +208,14 @@ b.pos = buf; b.last = buf + n; + h3c = ngx_http_v3_get_session(c); + h3c->total_bytes += n; + + if (ngx_http_v3_check_flood(c) != NGX_OK) { + ngx_http_v3_close_uni_stream(c); + return; + } + rc = ngx_http_v3_parse_uni(c, &us->parse, &b); if (rc == NGX_DONE) { @@ -282,6 +291,9 @@ p = (u_char *) ngx_http_v3_encode_varlen_int(p, push_id); n = p - buf; + h3c = ngx_http_v3_get_session(c); + h3c->total_bytes += n; + if (sc->send(sc, buf, n) != (ssize_t) n) { goto failed; } @@ -291,7 +303,6 @@ goto failed; } - h3c = ngx_http_v3_get_session(c); h3c->npushing++; cln->handler = ngx_http_v3_push_cleanup; @@ -383,6 +394,9 @@ n = (u_char *) ngx_http_v3_encode_varlen_int(buf, type) - buf; + h3c = ngx_http_v3_get_session(c); + h3c->total_bytes += n; + if (sc->send(sc, buf, n) != (ssize_t) n) { goto failed; } @@ -403,6 +417,7 @@ u_char *p, buf[NGX_HTTP_V3_VARLEN_INT_LEN * 6]; size_t n; ngx_connection_t *cc; + ngx_http_v3_session_t *h3c; ngx_http_v3_srv_conf_t *h3scf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 send settings"); @@ -431,6 +446,9 @@ p = (u_char *) ngx_http_v3_encode_varlen_int(p, h3scf->max_blocked_streams); n = p - buf; + h3c = ngx_http_v3_get_session(c); + h3c->total_bytes += n; + if (cc->send(cc, buf, n) != (ssize_t) n) { goto failed; } @@ -448,9 +466,10 @@ ngx_int_t ngx_http_v3_send_goaway(ngx_connection_t *c, uint64_t id) { - u_char *p, buf[NGX_HTTP_V3_VARLEN_INT_LEN * 3]; - size_t n; - ngx_connection_t *cc; + u_char *p, buf[NGX_HTTP_V3_VARLEN_INT_LEN * 3]; + size_t n; + ngx_connection_t *cc; + ngx_http_v3_session_t *h3c; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 send goaway %uL", id); @@ -465,6 +484,9 @@ p = (u_char *) ngx_http_v3_encode_varlen_int(p, id); n = p - buf; + h3c = ngx_http_v3_get_session(c); + h3c->total_bytes += n; + if (cc->send(cc, buf, n) != (ssize_t) n) { goto failed; } @@ -482,9 +504,10 @@ ngx_int_t ngx_http_v3_send_ack_section(ngx_connection_t *c, ngx_uint_t stream_id) { - u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; - size_t n; - ngx_connection_t *dc; + u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; + size_t n; + ngx_connection_t *dc; + ngx_http_v3_session_t *h3c; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client ack section %ui", stream_id); @@ -497,6 +520,9 @@ buf[0] = 0x80; n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 7) - buf; + h3c = ngx_http_v3_get_session(c); + h3c->total_bytes += n; + if (dc->send(dc, buf, n) != (ssize_t) n) { ngx_http_v3_close_uni_stream(dc); return NGX_ERROR; @@ -509,9 +535,10 @@ ngx_int_t ngx_http_v3_send_cancel_stream(ngx_connection_t *c, ngx_uint_t stream_id) { - u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; - size_t n; - ngx_connection_t *dc; + u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; + size_t n; + ngx_connection_t *dc; + ngx_http_v3_session_t *h3c; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client cancel stream %ui", stream_id); @@ -524,6 +551,9 @@ buf[0] = 0x40; n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 6) - buf; + h3c = ngx_http_v3_get_session(c); + h3c->total_bytes += n; + if (dc->send(dc, buf, n) != (ssize_t) n) { ngx_http_v3_close_uni_stream(dc); return NGX_ERROR; @@ -536,9 +566,10 @@ ngx_int_t ngx_http_v3_send_inc_insert_count(ngx_connection_t *c, ngx_uint_t inc) { - u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; - size_t n; - ngx_connection_t *dc; + u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; + size_t n; + ngx_connection_t *dc; + ngx_http_v3_session_t *h3c; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 client increment insert count %ui", inc); @@ -551,6 +582,9 @@ buf[0] = 0; n = (u_char *) ngx_http_v3_encode_prefix_int(buf, inc, 6) - buf; + h3c = ngx_http_v3_get_session(c); + h3c->total_bytes += n; + if (dc->send(dc, buf, n) != (ssize_t) n) { ngx_http_v3_close_uni_stream(dc); return NGX_ERROR;