changeset 8882:6204120cf37f quic

QUIC: traffic-based flood detection. With this patch, all traffic over a QUIC connection is compared to traffic over QUIC streams. As long as total traffic is many times larger than stream traffic, we consider this to be a flood.
author Roman Arutyunyan <arut@nginx.com>
date Wed, 13 Oct 2021 14:41:46 +0300
parents 72b304f6207c
children 404de224517e
files src/event/quic/ngx_event_quic.c src/event/quic/ngx_event_quic_connection.h
diffstat 2 files changed, 31 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/quic/ngx_event_quic.c
+++ b/src/event/quic/ngx_event_quic.c
@@ -665,13 +665,17 @@ ngx_quic_close_timer_handler(ngx_event_t
 static ngx_int_t
 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, ngx_quic_conf_t *conf)
 {
-    u_char             *p;
-    ngx_int_t           rc;
-    ngx_uint_t          good;
-    ngx_quic_header_t   pkt;
+    size_t                  size;
+    u_char                 *p;
+    ngx_int_t               rc;
+    ngx_uint_t              good;
+    ngx_quic_header_t       pkt;
+    ngx_quic_connection_t  *qc;
 
     good = 0;
 
+    size = b->last - b->pos;
+
     p = b->pos;
 
     while (p < b->last) {
@@ -736,7 +740,27 @@ ngx_quic_input(ngx_connection_t *c, ngx_
         p = b->pos;
     }
 
-    return good ? NGX_OK : NGX_DECLINED;
+    if (!good) {
+        return NGX_DECLINED;
+    }
+
+    qc = ngx_quic_get_connection(c);
+
+    if (qc) {
+        qc->received += size;
+
+        if ((uint64_t) (c->sent + qc->received) / 8 >
+            (qc->streams.sent + qc->streams.recv_last) + 1048576)
+        {
+            ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic flood detected");
+
+            qc->error = NGX_QUIC_ERR_NO_ERROR;
+            qc->error_reason = "QUIC flood detected";
+            return NGX_ERROR;
+        }
+    }
+
+    return NGX_OK;
 }
 
 
--- a/src/event/quic/ngx_event_quic_connection.h
+++ b/src/event/quic/ngx_event_quic_connection.h
@@ -236,6 +236,8 @@ struct ngx_quic_connection_s {
     ngx_quic_streams_t                streams;
     ngx_quic_congestion_t             congestion;
 
+    off_t                             received;
+
     ngx_uint_t                        error;
     enum ssl_encryption_level_t       error_level;
     ngx_uint_t                        error_ftype;