MEDIUM: quic: adjust address validation

When a new QUIC connection is created, server considers peer address as
not yet validated. The server must limit its sending up to 3 times the
content already received. This is a defensive measure to avoid flooding
a remote host victim of address spoofing.

This patch adjust the condition to consider the peer address as
validated. Two conditions are now considered :
* successful handling of a received HANDSHAKE packet. This was already
  done before although implemented in a different way.
* validation of a Retry token. This was not considered prior this patch
  despite RFC recommandation.

This patch also adjusts how a connection is internally labelled as using
a validated peer address. Before, above conditions were checked via
quic_peer_validated_addr(). Now, a flag QUIC_FL_CONN_PEER_VALIDATED_ADDR
is set to labelled this. It already existed prior this patch but was
only used for quic_cc_conn. This should now be more explicit.
This commit is contained in:
Amaury Denoyelle 2023-11-06 10:32:17 +01:00
parent 3a051ca0c8
commit d38bb7f8a7
3 changed files with 25 additions and 11 deletions

View File

@ -247,8 +247,7 @@ struct quic_connection_id {
uint tid; /* Attached Thread ID for the connection. */
};
/* Flag the packet number space as having received a packet */
#define QUIC_FL_PKTNS_PKT_RECEIVED (1UL << 0)
/* unused: 0x01 */
/* Flag the packet number space as requiring an ACK frame to be sent. */
#define QUIC_FL_PKTNS_ACK_REQUIRED (1UL << 1)
/* Flag the packet number space as needing probing */
@ -394,7 +393,7 @@ struct quic_conn_cntrs {
#define QUIC_FL_CONN_IO_TO_REQUEUE (1U << 14) /* IO handler must be requeued on new thread after connection migration */
#define QUIC_FL_CONN_IPKTNS_DCD (1U << 15) /* Initial packet number space discarded */
#define QUIC_FL_CONN_HPKTNS_DCD (1U << 16) /* Handshake packet number space discarded */
#define QUIC_FL_CONN_PEER_VALIDATED_ADDR (1U << 17) /* Connection with peer validated address */
#define QUIC_FL_CONN_PEER_VALIDATED_ADDR (1U << 17) /* Peer address is considered as validated for this connection. */
#define QUIC_FL_CONN_TO_KILL (1U << 24) /* Unusable connection, to be killed */
#define QUIC_FL_CONN_TX_TP_RECEIVED (1U << 25) /* Peer transport parameters have been received (used for the transmitting part) */
#define QUIC_FL_CONN_FINALIZED (1U << 26) /* QUIC connection finalized (functional, ready to send/receive) */

View File

@ -151,9 +151,7 @@ int quic_peer_validated_addr(struct quic_conn *qc)
if (!qc_is_listener(qc))
return 1;
if ((qc->hpktns && (qc->hpktns->flags & QUIC_FL_PKTNS_PKT_RECEIVED)) ||
(qc->apktns && (qc->apktns->flags & QUIC_FL_PKTNS_PKT_RECEIVED)) ||
qc->state >= QUIC_HS_ST_COMPLETE)
if (qc->flags & QUIC_FL_CONN_PEER_VALIDATED_ADDR)
return 1;
BUG_ON(qc->bytes.prep > 3 * qc->bytes.rx);
@ -845,8 +843,6 @@ static struct quic_cc_conn *qc_new_cc_conn(struct quic_conn *qc)
if (qc->fd >= 0)
fdtab[cc_qc->fd].owner = cc_qc;
cc_qc->flags = qc->flags;
if (quic_peer_validated_addr(qc))
cc_qc->flags |= QUIC_FL_CONN_PEER_VALIDATED_ADDR;
cc_qc->err = qc->err;
cc_qc->nb_pkt_for_cc = qc->nb_pkt_for_cc;
@ -1383,6 +1379,15 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
LIST_APPEND(&th_ctx->quic_conns, &qc->el_th_ctx);
qc->qc_epoch = HA_ATOMIC_LOAD(&qc_epoch);
/* If connection is instantiated due to an INITIAL packet with an
* already checked token, consider the peer address as validated.
*/
if (token_odcid->len) {
TRACE_STATE("validate peer address due to initial token",
QUIC_EV_CONN_INIT, qc);
qc->flags |= QUIC_FL_CONN_PEER_VALIDATED_ADDR;
}
TRACE_LEAVE(QUIC_EV_CONN_INIT, qc);
return qc;

View File

@ -1158,9 +1158,6 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
}
}
/* Flag this packet number space as having received a packet. */
qel->pktns->flags |= QUIC_FL_PKTNS_PKT_RECEIVED;
if (fast_retrans && qc->iel && qc->hel) {
struct quic_enc_level *iqel = qc->iel;
struct quic_enc_level *hqel = qc->hel;
@ -1381,6 +1378,19 @@ int qc_treat_rx_pkts(struct quic_conn *qc)
else {
struct quic_arng ar = { .first = pkt->pn, .last = pkt->pn };
/* RFC 9000 8.1. Address Validation during Connection Establishment
*
* Connection establishment implicitly provides address validation for
* both endpoints. In particular, receipt of a packet protected with
* Handshake keys confirms that the peer successfully processed an
* Initial packet.
*/
if (qel == qc->hel) {
TRACE_STATE("validate peer address on handshake packet",
QUIC_EV_CONN_RXPKT, qc, pkt);
qc->flags |= QUIC_FL_CONN_PEER_VALIDATED_ADDR;
}
/* Update the list of ranges to acknowledge. */
if (quic_update_ack_ranges_list(qc, &qel->pktns->rx.arngs, &ar)) {
if (pkt->flags & QUIC_FL_RX_PACKET_ACK_ELICITING) {