mirror of
https://github.com/nginx/nginx.git
synced 2024-12-18 07:37:49 +08:00
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.
This commit is contained in:
parent
6e7f192804
commit
a31745499b
@ -86,6 +86,7 @@ struct ngx_quic_path_s {
|
|||||||
socklen_t socklen;
|
socklen_t socklen;
|
||||||
ngx_uint_t state;
|
ngx_uint_t state;
|
||||||
ngx_msec_t expires;
|
ngx_msec_t expires;
|
||||||
|
ngx_msec_t last_seen;
|
||||||
ngx_uint_t tries;
|
ngx_uint_t tries;
|
||||||
off_t sent;
|
off_t sent;
|
||||||
off_t received;
|
off_t received;
|
||||||
@ -93,7 +94,6 @@ struct ngx_quic_path_s {
|
|||||||
u_char challenge2[8];
|
u_char challenge2[8];
|
||||||
ngx_uint_t refcnt;
|
ngx_uint_t refcnt;
|
||||||
uint64_t seqnum;
|
uint64_t seqnum;
|
||||||
time_t validated_at;
|
|
||||||
ngx_str_t addr_text;
|
ngx_str_t addr_text;
|
||||||
u_char text[NGX_SOCKADDR_STRLEN];
|
u_char text[NGX_SOCKADDR_STRLEN];
|
||||||
};
|
};
|
||||||
|
@ -158,7 +158,6 @@ valid:
|
|||||||
"quic path #%uL successfully validated", path->seqnum);
|
"quic path #%uL successfully validated", path->seqnum);
|
||||||
|
|
||||||
path->state = NGX_QUIC_PATH_VALIDATED;
|
path->state = NGX_QUIC_PATH_VALIDATED;
|
||||||
path->validated_at = ngx_time();
|
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@ -217,6 +216,7 @@ ngx_quic_add_path(ngx_connection_t *c, struct sockaddr *sockaddr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
path->seqnum = qc->path_seqnum++;
|
path->seqnum = qc->path_seqnum++;
|
||||||
|
path->last_seen = ngx_current_msec;
|
||||||
|
|
||||||
path->socklen = socklen;
|
path->socklen = socklen;
|
||||||
ngx_memcpy(path->sockaddr, sockaddr, socklen);
|
ngx_memcpy(path->sockaddr, sockaddr, socklen);
|
||||||
@ -272,6 +272,7 @@ ngx_quic_update_paths(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
ngx_quic_client_id_t *cid;
|
ngx_quic_client_id_t *cid;
|
||||||
ngx_quic_connection_t *qc;
|
ngx_quic_connection_t *qc;
|
||||||
|
|
||||||
|
qc = ngx_quic_get_connection(c);
|
||||||
qsock = ngx_quic_get_socket(c);
|
qsock = ngx_quic_get_socket(c);
|
||||||
|
|
||||||
if (c->udp->dgram == NULL) {
|
if (c->udp->dgram == NULL) {
|
||||||
@ -313,7 +314,6 @@ ngx_quic_update_paths(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
cid = ngx_quic_used_client_id(c, path);
|
cid = ngx_quic_used_client_id(c, path);
|
||||||
if (cid == NULL) {
|
if (cid == NULL) {
|
||||||
|
|
||||||
qc = ngx_quic_get_connection(c);
|
|
||||||
qc->error = NGX_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR;
|
qc->error = NGX_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR;
|
||||||
qc->error_reason = "no available client ids for new path";
|
qc->error_reason = "no available client ids for new path";
|
||||||
|
|
||||||
@ -328,6 +328,17 @@ ngx_quic_update_paths(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
|
|
||||||
update:
|
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;
|
len = pkt->raw->last - pkt->raw->start;
|
||||||
|
|
||||||
/* TODO: this may be too late in some cases;
|
/* TODO: this may be too late in some cases;
|
||||||
@ -396,31 +407,10 @@ ngx_quic_handle_migration(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
qsock->sid.seqnum, qsock->cid->seqnum, next->seqnum,
|
qsock->sid.seqnum, qsock->cid->seqnum, next->seqnum,
|
||||||
ngx_quic_path_state_str(next));
|
ngx_quic_path_state_str(next));
|
||||||
|
|
||||||
switch (next->state) {
|
if (next->state == NGX_QUIC_PATH_NEW) {
|
||||||
case NGX_QUIC_PATH_NEW:
|
|
||||||
if (ngx_quic_validate_path(c, qsock) != NGX_OK) {
|
if (ngx_quic_validate_path(c, qsock) != NGX_OK) {
|
||||||
return NGX_ERROR;
|
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);
|
ctx = ngx_quic_get_send_ctx(qc, pkt->level);
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
#define NGX_QUIC_PATH_VALIDATING 1
|
#define NGX_QUIC_PATH_VALIDATING 1
|
||||||
#define NGX_QUIC_PATH_VALIDATED 2
|
#define NGX_QUIC_PATH_VALIDATED 2
|
||||||
|
|
||||||
#define NGX_QUIC_PATH_VALID_TIME 600 /* seconds */
|
|
||||||
|
|
||||||
|
|
||||||
#define ngx_quic_path_state_str(p) \
|
#define ngx_quic_path_state_str(p) \
|
||||||
((p)->state == NGX_QUIC_PATH_NEW) ? "new" : \
|
((p)->state == NGX_QUIC_PATH_NEW) ? "new" : \
|
||||||
|
@ -82,7 +82,6 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc,
|
|||||||
|
|
||||||
if (pkt->validated) {
|
if (pkt->validated) {
|
||||||
path->state = NGX_QUIC_PATH_VALIDATED;
|
path->state = NGX_QUIC_PATH_VALIDATED;
|
||||||
path->validated_at = ngx_time();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now bind socket to client and path */
|
/* now bind socket to client and path */
|
||||||
|
Loading…
Reference in New Issue
Block a user