# HG changeset patch # User Vladimir Homutov # Date 1594906562 -10800 # Node ID 031918df51c0d7c11b5b79f9e2b3ff6d002ce20a # Parent f9fbeb4ee0deca58337208e4a186cbb7a73c7f1f QUIC: added anti-amplification limit. According to quic-transport draft 29, section 21.12.1.1: Prior to validation, endpoints are limited in what they are able to send. During the handshake, a server cannot send more than three times the data it receives; clients that initiate new connections or migrate to a new network path are limited. diff --git a/src/event/ngx_event_quic.c b/src/event/ngx_event_quic.c --- a/src/event/ngx_event_quic.c +++ b/src/event/ngx_event_quic.c @@ -114,6 +114,7 @@ struct ngx_quic_connection_s { ngx_quic_streams_t streams; ngx_quic_congestion_t congestion; + size_t received; uint64_t cur_streams; uint64_t max_streams; @@ -130,6 +131,7 @@ struct ngx_quic_connection_s { unsigned key_phase:1; unsigned in_retry:1; unsigned initialized:1; + unsigned validated:1; }; @@ -689,6 +691,8 @@ ngx_quic_new_connection(ngx_connection_t * qc->latest_rtt = 0 */ + qc->received = pkt->raw->last - pkt->raw->start; + qc->pto.log = c->log; qc->pto.data = c; qc->pto.handler = ngx_quic_pto_handler; @@ -763,6 +767,7 @@ ngx_quic_new_connection(ngx_connection_t } /* NGX_OK */ + qc->validated = 1; } else if (tp->retry) { return ngx_quic_retry(c); @@ -1240,6 +1245,7 @@ ngx_quic_input_handler(ngx_event_t *rev) } b.last += n; + qc->received += n; if (ngx_quic_input(c, &b) != NGX_OK) { ngx_quic_close_connection(c, NGX_ERROR); @@ -1639,6 +1645,8 @@ ngx_quic_retry_input(ngx_connection_t *c return NGX_ERROR; } + qc->validated = 1; + pkt->secret = &keys->client; pkt->level = ssl_encryption_initial; pkt->plaintext = buf; @@ -1759,6 +1767,7 @@ ngx_quic_handshake_input(ngx_connection_ ctx = ngx_quic_get_send_ctx(c->quic, ssl_encryption_initial); ngx_quic_free_frames(c, &ctx->sent); + qc->validated = 1; qc->pto_count = 0; return ngx_quic_payload_handler(c, pkt); @@ -3368,6 +3377,22 @@ ngx_quic_output_frames(ngx_connection_t break; } + if (!qc->validated) { + /* + * Prior to validation, endpoints are limited in what they + * are able to send. During the handshake, a server cannot + * send more than three times the data it receives; + */ + + if (((c->sent + len + f->len) / 3) > qc->received) { + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "quic hit amplification limit" + " received %uz sent %O", + qc->received, c->sent); + break; + } + } + q = ngx_queue_next(q); f->first = ngx_current_msec;