[PATCH 4 of 5] QUIC: traffic-based flood detection
Roman Arutyunyan
arut at nginx.com
Wed Oct 13 11:41:38 UTC 2021
On Tue, Oct 12, 2021 at 03:39:38PM +0300, Vladimir Homutov wrote:
> On Thu, Oct 07, 2021 at 02:36:17PM +0300, Roman Arutyunyan wrote:
> > # HG changeset patch
> > # User Roman Arutyunyan <arut at nginx.com>
> > # Date 1633602816 -10800
> > # Thu Oct 07 13:33:36 2021 +0300
> > # Branch quic
> > # Node ID e20f00b8ac9005621993ea19375b1646c9182e7b
> > # Parent 31561ac584b74d29af9a442afca47821a98217b2
> > 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.
> >
> > diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c
> > --- a/src/event/quic/ngx_event_quic.c
> > +++ b/src/event/quic/ngx_event_quic.c
> > @@ -662,13 +662,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) {
> > @@ -701,7 +705,8 @@ ngx_quic_input(ngx_connection_t *c, ngx_
> >
> > if (rc == NGX_DONE) {
> > /* stop further processing */
> > - return NGX_DECLINED;
> > + good = 0;
> > + break;
> > }
>
> this chunk looks unnecessary: we will test 'good' after the loop and
> return NGX_DECLINED anyway in this case (good = 0).
Sure, thanks. Removed this one.
> > if (rc == NGX_OK) {
> > @@ -733,7 +738,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)
> > + {
>
> note: the comparison is intentionally similar to one used HTTP/2 for the
> same purposes
>
> > + 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;
> > }
> >
> >
> > diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h
> > --- 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;
>
> As a whole, it seems to be working good enough.
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-devel
--
Roman Arutyunyan
More information about the nginx-devel
mailing list