Mercurial > hg > nginx
diff src/http/v3/ngx_http_v3_filter_module.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 | 5a2080d48da8 |
children | 8d0753760546 |
line wrap: on
line diff
--- a/src/http/v3/ngx_http_v3_filter_module.c Wed Oct 06 14:51:16 2021 +0300 +++ b/src/http/v3/ngx_http_v3_filter_module.c Thu Oct 07 13:22:42 2021 +0300 @@ -101,6 +101,7 @@ ngx_list_part_t *part; ngx_table_elt_t *header; ngx_connection_t *c; + ngx_http_v3_session_t *h3c; ngx_http_v3_filter_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; @@ -120,6 +121,8 @@ return NGX_OK; } + h3c = ngx_http_v3_get_session(r->connection); + if (r->method == NGX_HTTP_HEAD) { r->header_only = 1; } @@ -531,6 +534,8 @@ n = b->last - b->pos; + h3c->payload_bytes += n; + len = ngx_http_v3_encode_varlen_int(NULL, NGX_HTTP_V3_FRAME_HEADERS) + ngx_http_v3_encode_varlen_int(NULL, n); @@ -571,6 +576,9 @@ b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, r->headers_out.content_length_n); + h3c->payload_bytes += r->headers_out.content_length_n; + h3c->total_bytes += r->headers_out.content_length_n; + cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; @@ -590,6 +598,10 @@ ngx_http_set_ctx(r, ctx, ngx_http_v3_filter_module); } + for (cl = out; cl; cl = cl->next) { + h3c->total_bytes += cl->buf->last - cl->buf->pos; + } + return ngx_http_write_filter(r, out); } @@ -1096,9 +1108,12 @@ ngx_http_v3_create_push_promise(ngx_http_request_t *r, ngx_str_t *path, uint64_t push_id) { - size_t n, len; - ngx_buf_t *b; - ngx_chain_t *hl, *cl; + size_t n, len; + ngx_buf_t *b; + ngx_chain_t *hl, *cl; + ngx_http_v3_session_t *h3c; + + h3c = ngx_http_v3_get_session(r->connection); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http3 create push promise id:%uL", push_id); @@ -1233,6 +1248,8 @@ n = b->last - b->pos; + h3c->payload_bytes += n; + len = ngx_http_v3_encode_varlen_int(NULL, NGX_HTTP_V3_FRAME_PUSH_PROMISE) + ngx_http_v3_encode_varlen_int(NULL, n); @@ -1265,6 +1282,7 @@ ngx_int_t rc; ngx_buf_t *b; ngx_chain_t *out, *cl, *tl, **ll; + ngx_http_v3_session_t *h3c; ngx_http_v3_filter_ctx_t *ctx; if (in == NULL) { @@ -1276,6 +1294,8 @@ return ngx_http_next_body_filter(r, in); } + h3c = ngx_http_v3_get_session(r->connection); + out = NULL; ll = &out; @@ -1340,6 +1360,8 @@ tl->next = out; out = tl; + + h3c->payload_bytes += size; } if (cl->buf->last_buf) { @@ -1356,6 +1378,10 @@ *ll = NULL; } + for (cl = out; cl; cl = cl->next) { + h3c->total_bytes += cl->buf->last - cl->buf->pos; + } + rc = ngx_http_next_body_filter(r, out); ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &out, @@ -1369,13 +1395,16 @@ ngx_http_v3_create_trailers(ngx_http_request_t *r, ngx_http_v3_filter_ctx_t *ctx) { - size_t len, n; - u_char *p; - ngx_buf_t *b; - ngx_uint_t i; - ngx_chain_t *cl, *hl; - ngx_list_part_t *part; - ngx_table_elt_t *header; + size_t len, n; + u_char *p; + ngx_buf_t *b; + ngx_uint_t i; + ngx_chain_t *cl, *hl; + ngx_list_part_t *part; + ngx_table_elt_t *header; + ngx_http_v3_session_t *h3c; + + h3c = ngx_http_v3_get_session(r->connection); len = 0; @@ -1461,6 +1490,8 @@ n = b->last - b->pos; + h3c->payload_bytes += n; + hl = ngx_chain_get_free_buf(r->pool, &ctx->free); if (hl == NULL) { return NULL;