mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Fix amplification mitigation in 0-RTT case.
From the spec: Prior to validating the client address, servers MUST NOT send more than three times as many bytes as the number of bytes they have received. This limits the magnitude of any amplification attack that can be mounted using spoofed source addresses. In determining this limit, servers only count the size of successfully processed packets.
This commit is contained in:
parent
652129e69b
commit
10f94146d0
5 changed files with 85 additions and 8 deletions
|
@ -57,6 +57,11 @@ struct lsquic_conn_public {
|
|||
#if LSQUIC_EXTRA_CHECKS
|
||||
unsigned long stream_frame_bytes;
|
||||
#endif
|
||||
/* "unsigned" is wide enough: these values are only used for amplification
|
||||
* limit before initial path is validated.
|
||||
*/
|
||||
unsigned bytes_in; /* successfully processed */
|
||||
unsigned bytes_out;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -137,6 +137,12 @@ enum ifull_conn_flags
|
|||
};
|
||||
|
||||
|
||||
enum more_flags
|
||||
{
|
||||
MF_VALIDATE_PATH = 1 << 0,
|
||||
};
|
||||
|
||||
|
||||
#define N_PATHS 2
|
||||
|
||||
enum send
|
||||
|
@ -314,6 +320,7 @@ struct ietf_full_conn
|
|||
unsigned ifc_max_streams_in[N_SDS];
|
||||
uint64_t ifc_max_stream_data_uni;
|
||||
enum ifull_conn_flags ifc_flags;
|
||||
enum more_flags ifc_mflags;
|
||||
enum send_flags ifc_send_flags;
|
||||
enum send_flags ifc_delayed_send;
|
||||
struct {
|
||||
|
@ -1306,6 +1313,12 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
|
|||
conn->ifc_paths[0].cop_path = imc->imc_path;
|
||||
conn->ifc_paths[0].cop_flags = COP_VALIDATED;
|
||||
conn->ifc_used_paths = 1 << 0;
|
||||
if (imc->imc_flags & IMC_ADDR_VALIDATED)
|
||||
lsquic_send_ctl_path_validated(&conn->ifc_send_ctl);
|
||||
else
|
||||
conn->ifc_mflags |= MF_VALIDATE_PATH;
|
||||
conn->ifc_pub.bytes_out = imc->imc_bytes_out;
|
||||
conn->ifc_pub.bytes_in = imc->imc_bytes_in;
|
||||
if (imc->imc_flags & IMC_PATH_CHANGED)
|
||||
{
|
||||
LSQ_DEBUG("path changed during mini conn: schedule PATH_CHALLENGE");
|
||||
|
@ -6369,6 +6382,14 @@ process_regular_packet (struct ietf_full_conn *conn,
|
|||
else
|
||||
conn->ifc_spin_bit = !lsquic_packet_in_spin_bit(packet_in);
|
||||
}
|
||||
conn->ifc_pub.bytes_in += packet_in->pi_data_sz;
|
||||
if ((conn->ifc_mflags & MF_VALIDATE_PATH) &&
|
||||
(packet_in->pi_header_type == HETY_NOT_SET
|
||||
|| packet_in->pi_header_type == HETY_HANDSHAKE))
|
||||
{
|
||||
conn->ifc_mflags &= ~MF_VALIDATE_PATH;
|
||||
lsquic_send_ctl_path_validated(&conn->ifc_send_ctl);
|
||||
}
|
||||
return 0;
|
||||
case REC_ST_DUP:
|
||||
LSQ_INFO("packet %"PRIu64" is a duplicate", packet_in->pi_packno);
|
||||
|
@ -6567,6 +6588,8 @@ ietf_full_conn_ci_packet_sent (struct lsquic_conn *lconn,
|
|||
lsquic_alarmset_set(&conn->ifc_alset, AL_BLOCKED_KA,
|
||||
packet_out->po_sent + (1 + (7 & lsquic_crand_get_nybble(
|
||||
conn->ifc_enpub->enp_crand))) * 1000000);
|
||||
conn->ifc_pub.bytes_out += lsquic_packet_out_sent_sz(&conn->ifc_conn,
|
||||
packet_out);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -214,7 +214,7 @@ typedef struct lsquic_packet_out
|
|||
lconn->cn_pf->pf_packout_max_header_size(lconn, po_flags, dcid_len))
|
||||
|
||||
#define lsquic_packet_out_total_sz(lconn, p) (\
|
||||
lconn->cn_pf->pf_packout_size(lconn, p))
|
||||
(lconn)->cn_pf->pf_packout_size(lconn, p))
|
||||
|
||||
#if __GNUC__
|
||||
#if LSQUIC_EXTRA_CHECKS
|
||||
|
|
|
@ -119,6 +119,12 @@ send_ctl_all_bytes_out (const struct lsquic_send_ctl *ctl);
|
|||
static void
|
||||
send_ctl_reschedule_poison (struct lsquic_send_ctl *ctl);
|
||||
|
||||
static int
|
||||
send_ctl_can_send_pre_hsk (struct lsquic_send_ctl *ctl);
|
||||
|
||||
static int
|
||||
send_ctl_can_send (struct lsquic_send_ctl *ctl);
|
||||
|
||||
#ifdef NDEBUG
|
||||
static
|
||||
#elif __GNUC__
|
||||
|
@ -363,6 +369,11 @@ lsquic_send_ctl_init (lsquic_send_ctl_t *ctl, struct lsquic_alarmset *alset,
|
|||
ctl->sc_flags |= SC_SANITY_CHECK;
|
||||
#endif
|
||||
ctl->sc_gap = UINT64_MAX - 1 /* Can't have +1 == 0 */;
|
||||
if ((ctl->sc_conn_pub->lconn->cn_flags & (LSCONN_IETF|LSCONN_SERVER))
|
||||
== (LSCONN_IETF|LSCONN_SERVER))
|
||||
ctl->sc_can_send = send_ctl_can_send_pre_hsk;
|
||||
else
|
||||
ctl->sc_can_send = send_ctl_can_send;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1367,13 +1378,8 @@ lsquic_send_ctl_pacer_blocked (struct lsquic_send_ctl *ctl)
|
|||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
#if __GNUC__
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
#endif
|
||||
int
|
||||
lsquic_send_ctl_can_send (lsquic_send_ctl_t *ctl)
|
||||
static int
|
||||
send_ctl_can_send (struct lsquic_send_ctl *ctl)
|
||||
{
|
||||
const unsigned n_out = send_ctl_all_bytes_out(ctl);
|
||||
LSQ_DEBUG("%s: n_out: %u (unacked_all: %u); cwnd: %"PRIu64, __func__,
|
||||
|
@ -1400,6 +1406,37 @@ lsquic_send_ctl_can_send (lsquic_send_ctl_t *ctl)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
send_ctl_can_send_pre_hsk (struct lsquic_send_ctl *ctl)
|
||||
{
|
||||
unsigned bytes_in, bytes_out;
|
||||
|
||||
bytes_in = ctl->sc_conn_pub->bytes_in;
|
||||
bytes_out = ctl->sc_conn_pub->bytes_out + ctl->sc_bytes_scheduled;
|
||||
if (bytes_out >= bytes_in * 2 + bytes_in / 2 /* This should work out
|
||||
to around 3 on average */)
|
||||
{
|
||||
LSQ_DEBUG("%s: amplification block: %u bytes in, %u bytes out",
|
||||
__func__, bytes_in, bytes_out);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return send_ctl_can_send(ctl);
|
||||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
#if __GNUC__
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
#endif
|
||||
int
|
||||
lsquic_send_ctl_can_send (struct lsquic_send_ctl *ctl)
|
||||
{
|
||||
return ctl->sc_can_send(ctl);
|
||||
}
|
||||
|
||||
|
||||
/* Like lsquic_send_ctl_can_send(), but no mods */
|
||||
static int
|
||||
send_ctl_could_send (const struct lsquic_send_ctl *ctl)
|
||||
|
@ -2982,3 +3019,11 @@ lsquic_send_ctl_begin_optack_detection (struct lsquic_send_ctl *ctl)
|
|||
rand = lsquic_crand_get_byte(ctl->sc_enpub->enp_crand);
|
||||
ctl->sc_gap = ctl->sc_cur_packno + 1 + rand;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_send_ctl_path_validated (struct lsquic_send_ctl *ctl)
|
||||
{
|
||||
LSQ_DEBUG("path validated: switch to regular can_send");
|
||||
ctl->sc_can_send = send_ctl_can_send;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ typedef struct lsquic_send_ctl {
|
|||
lsquic_time_t sc_largest_acked_sent_time;
|
||||
lsquic_time_t sc_last_sent_time;
|
||||
lsquic_time_t sc_last_rto_time;
|
||||
int (*sc_can_send)(struct lsquic_send_ctl *);
|
||||
unsigned sc_bytes_unacked_retx;
|
||||
unsigned sc_bytes_scheduled;
|
||||
union {
|
||||
|
@ -383,4 +384,7 @@ lsquic_send_ctl_begin_optack_detection (struct lsquic_send_ctl *);
|
|||
|
||||
#define lsquic_send_ctl_n_unacked(ctl_) ((ctl_)->sc_n_in_flight_retx)
|
||||
|
||||
void
|
||||
lsquic_send_ctl_path_validated (struct lsquic_send_ctl *);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue