comparison src/event/ngx_event_quic.c @ 8477: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
8476:f9fbeb4ee0de 8477: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);