Mercurial > hg > nginx-quic
comparison src/event/ngx_event_quic.c @ 7995:031918df51c0 quic
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.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Thu, 16 Jul 2020 16:36:02 +0300 |
parents | f9fbeb4ee0de |
children | d2f716e668e8 |
comparison
equal
deleted
inserted
replaced
7994:f9fbeb4ee0de | 7995:031918df51c0 |
---|---|
112 ngx_uint_t nframes; | 112 ngx_uint_t nframes; |
113 #endif | 113 #endif |
114 | 114 |
115 ngx_quic_streams_t streams; | 115 ngx_quic_streams_t streams; |
116 ngx_quic_congestion_t congestion; | 116 ngx_quic_congestion_t congestion; |
117 size_t received; | |
117 | 118 |
118 uint64_t cur_streams; | 119 uint64_t cur_streams; |
119 uint64_t max_streams; | 120 uint64_t max_streams; |
120 | 121 |
121 ngx_uint_t error; | 122 ngx_uint_t error; |
128 unsigned closing:1; | 129 unsigned closing:1; |
129 unsigned draining:1; | 130 unsigned draining:1; |
130 unsigned key_phase:1; | 131 unsigned key_phase:1; |
131 unsigned in_retry:1; | 132 unsigned in_retry:1; |
132 unsigned initialized:1; | 133 unsigned initialized:1; |
134 unsigned validated:1; | |
133 }; | 135 }; |
134 | 136 |
135 | 137 |
136 typedef ngx_int_t (*ngx_quic_frame_handler_pt)(ngx_connection_t *c, | 138 typedef ngx_int_t (*ngx_quic_frame_handler_pt)(ngx_connection_t *c, |
137 ngx_quic_frame_t *frame, void *data); | 139 ngx_quic_frame_t *frame, void *data); |
687 | 689 |
688 /* | 690 /* |
689 * qc->latest_rtt = 0 | 691 * qc->latest_rtt = 0 |
690 */ | 692 */ |
691 | 693 |
694 qc->received = pkt->raw->last - pkt->raw->start; | |
695 | |
692 qc->pto.log = c->log; | 696 qc->pto.log = c->log; |
693 qc->pto.data = c; | 697 qc->pto.data = c; |
694 qc->pto.handler = ngx_quic_pto_handler; | 698 qc->pto.handler = ngx_quic_pto_handler; |
695 qc->pto.cancelable = 1; | 699 qc->pto.cancelable = 1; |
696 | 700 |
761 ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic expired token"); | 765 ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic expired token"); |
762 return ngx_quic_retry(c); | 766 return ngx_quic_retry(c); |
763 } | 767 } |
764 | 768 |
765 /* NGX_OK */ | 769 /* NGX_OK */ |
770 qc->validated = 1; | |
766 | 771 |
767 } else if (tp->retry) { | 772 } else if (tp->retry) { |
768 return ngx_quic_retry(c); | 773 return ngx_quic_retry(c); |
769 } | 774 } |
770 | 775 |
1238 ngx_quic_close_connection(c, NGX_ERROR); | 1243 ngx_quic_close_connection(c, NGX_ERROR); |
1239 return; | 1244 return; |
1240 } | 1245 } |
1241 | 1246 |
1242 b.last += n; | 1247 b.last += n; |
1248 qc->received += n; | |
1243 | 1249 |
1244 if (ngx_quic_input(c, &b) != NGX_OK) { | 1250 if (ngx_quic_input(c, &b) != NGX_OK) { |
1245 ngx_quic_close_connection(c, NGX_ERROR); | 1251 ngx_quic_close_connection(c, NGX_ERROR); |
1246 return; | 1252 return; |
1247 } | 1253 } |
1637 if (ngx_quic_validate_token(c, pkt) != NGX_OK) { | 1643 if (ngx_quic_validate_token(c, pkt) != NGX_OK) { |
1638 ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic invalid token"); | 1644 ngx_log_error(NGX_LOG_INFO, c->log, 0, "quic invalid token"); |
1639 return NGX_ERROR; | 1645 return NGX_ERROR; |
1640 } | 1646 } |
1641 | 1647 |
1648 qc->validated = 1; | |
1649 | |
1642 pkt->secret = &keys->client; | 1650 pkt->secret = &keys->client; |
1643 pkt->level = ssl_encryption_initial; | 1651 pkt->level = ssl_encryption_initial; |
1644 pkt->plaintext = buf; | 1652 pkt->plaintext = buf; |
1645 | 1653 |
1646 ctx = ngx_quic_get_send_ctx(qc, pkt->level); | 1654 ctx = ngx_quic_get_send_ctx(qc, pkt->level); |
1757 * that no more Initial packets need to be exchanged | 1765 * that no more Initial packets need to be exchanged |
1758 */ | 1766 */ |
1759 ctx = ngx_quic_get_send_ctx(c->quic, ssl_encryption_initial); | 1767 ctx = ngx_quic_get_send_ctx(c->quic, ssl_encryption_initial); |
1760 ngx_quic_free_frames(c, &ctx->sent); | 1768 ngx_quic_free_frames(c, &ctx->sent); |
1761 | 1769 |
1770 qc->validated = 1; | |
1762 qc->pto_count = 0; | 1771 qc->pto_count = 0; |
1763 | 1772 |
1764 return ngx_quic_payload_handler(c, pkt); | 1773 return ngx_quic_payload_handler(c, pkt); |
1765 } | 1774 } |
1766 | 1775 |
3366 | 3375 |
3367 if (need_ack && cg->in_flight + len + f->len > cg->window) { | 3376 if (need_ack && cg->in_flight + len + f->len > cg->window) { |
3368 break; | 3377 break; |
3369 } | 3378 } |
3370 | 3379 |
3380 if (!qc->validated) { | |
3381 /* | |
3382 * Prior to validation, endpoints are limited in what they | |
3383 * are able to send. During the handshake, a server cannot | |
3384 * send more than three times the data it receives; | |
3385 */ | |
3386 | |
3387 if (((c->sent + len + f->len) / 3) > qc->received) { | |
3388 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
3389 "quic hit amplification limit" | |
3390 " received %uz sent %O", | |
3391 qc->received, c->sent); | |
3392 break; | |
3393 } | |
3394 } | |
3395 | |
3371 q = ngx_queue_next(q); | 3396 q = ngx_queue_next(q); |
3372 | 3397 |
3373 f->first = ngx_current_msec; | 3398 f->first = ngx_current_msec; |
3374 | 3399 |
3375 ngx_queue_remove(&f->queue); | 3400 ngx_queue_remove(&f->queue); |