# HG changeset patch # User Vladimir Homutov # Date 1639405649 -10800 # Node ID ddd5e5c0f87df68f665284827ea418098b241515 # Parent 23880e4ad3e2986c189cf61d8409066f2b31590e QUIC: improved path validation. Previously, path was considered valid during arbitrary selected 10m timeout since validation. This is quite not what RFC 9000 says; the relevant part is: An endpoint MAY skip validation of a peer address if that address has been seen recently. The patch considers a path to be 'recently seen' if packets were received during idle timeout. If a packet is received from the path that was seen not so recently, such path is considered new, and anti-amplification restrictions apply. 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 @@ -86,6 +86,7 @@ struct ngx_quic_path_s { socklen_t socklen; ngx_uint_t state; ngx_msec_t expires; + ngx_msec_t last_seen; ngx_uint_t tries; off_t sent; off_t received; @@ -93,7 +94,6 @@ struct ngx_quic_path_s { u_char challenge2[8]; ngx_uint_t refcnt; uint64_t seqnum; - time_t validated_at; ngx_str_t addr_text; u_char text[NGX_SOCKADDR_STRLEN]; }; diff --git a/src/event/quic/ngx_event_quic_migration.c b/src/event/quic/ngx_event_quic_migration.c --- a/src/event/quic/ngx_event_quic_migration.c +++ b/src/event/quic/ngx_event_quic_migration.c @@ -158,7 +158,6 @@ valid: "quic path #%uL successfully validated", path->seqnum); path->state = NGX_QUIC_PATH_VALIDATED; - path->validated_at = ngx_time(); return NGX_OK; } @@ -217,6 +216,7 @@ ngx_quic_add_path(ngx_connection_t *c, s } path->seqnum = qc->path_seqnum++; + path->last_seen = ngx_current_msec; path->socklen = socklen; ngx_memcpy(path->sockaddr, sockaddr, socklen); @@ -272,6 +272,7 @@ ngx_quic_update_paths(ngx_connection_t * ngx_quic_client_id_t *cid; ngx_quic_connection_t *qc; + qc = ngx_quic_get_connection(c); qsock = ngx_quic_get_socket(c); if (c->udp->dgram == NULL) { @@ -313,7 +314,6 @@ ngx_quic_update_paths(ngx_connection_t * cid = ngx_quic_used_client_id(c, path); if (cid == NULL) { - qc = ngx_quic_get_connection(c); qc->error = NGX_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR; qc->error_reason = "no available client ids for new path"; @@ -328,6 +328,17 @@ ngx_quic_update_paths(ngx_connection_t * update: + if (path->state != NGX_QUIC_PATH_NEW) { + /* force limits/revalidation for paths that were not seen recently */ + if (ngx_current_msec - path->last_seen > qc->tp.max_idle_timeout) { + path->state = NGX_QUIC_PATH_NEW; + path->sent = 0; + path->received = 0; + } + } + + path->last_seen = ngx_current_msec; + len = pkt->raw->last - pkt->raw->start; /* TODO: this may be too late in some cases; @@ -396,31 +407,10 @@ ngx_quic_handle_migration(ngx_connection qsock->sid.seqnum, qsock->cid->seqnum, next->seqnum, ngx_quic_path_state_str(next)); - switch (next->state) { - case NGX_QUIC_PATH_NEW: + if (next->state == NGX_QUIC_PATH_NEW) { if (ngx_quic_validate_path(c, qsock) != NGX_OK) { return NGX_ERROR; } - break; - - /* migration to previously known path */ - - case NGX_QUIC_PATH_VALIDATING: - /* alredy validating, nothing to do */ - break; - - case NGX_QUIC_PATH_VALIDATED: - /* if path is old enough, revalidate */ - if (ngx_time() - next->validated_at > NGX_QUIC_PATH_VALID_TIME) { - - next->state = NGX_QUIC_PATH_NEW; - - if (ngx_quic_validate_path(c, qsock) != NGX_OK) { - return NGX_ERROR; - } - } - - break; } ctx = ngx_quic_get_send_ctx(qc, pkt->level); diff --git a/src/event/quic/ngx_event_quic_migration.h b/src/event/quic/ngx_event_quic_migration.h --- a/src/event/quic/ngx_event_quic_migration.h +++ b/src/event/quic/ngx_event_quic_migration.h @@ -17,8 +17,6 @@ #define NGX_QUIC_PATH_VALIDATING 1 #define NGX_QUIC_PATH_VALIDATED 2 -#define NGX_QUIC_PATH_VALID_TIME 600 /* seconds */ - #define ngx_quic_path_state_str(p) \ ((p)->state == NGX_QUIC_PATH_NEW) ? "new" : \ diff --git a/src/event/quic/ngx_event_quic_socket.c b/src/event/quic/ngx_event_quic_socket.c --- a/src/event/quic/ngx_event_quic_socket.c +++ b/src/event/quic/ngx_event_quic_socket.c @@ -82,7 +82,6 @@ ngx_quic_open_sockets(ngx_connection_t * if (pkt->validated) { path->state = NGX_QUIC_PATH_VALIDATED; - path->validated_at = ngx_time(); } /* now bind socket to client and path */