QUIC: Stateless Reset rate limiting.

It uses a bloom filter to limit sending Stateless Reset packets no more
than once per second in average for the given address.  This allows to
address resource asymmetry from precomputed packets, as well as to limit
potential Stateless Reset exchange.
pull/1161/head
Sergey Kandaurov 2 weeks ago committed by Sergey Kandaurov
parent 2f039e6f72
commit e6ffe8384e
  1. 65
      src/event/quic/ngx_event_quic_output.c

@ -64,6 +64,7 @@ static ssize_t ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len,
struct sockaddr *sockaddr, socklen_t socklen);
static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt,
ngx_quic_send_ctx_t *ctx);
static ngx_int_t ngx_quic_stateless_reset_filter(ngx_connection_t *c);
ngx_int_t
@ -823,10 +824,11 @@ ngx_int_t
ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf,
ngx_quic_header_t *pkt)
{
u_char *token;
size_t len, max;
uint16_t rndbytes;
u_char buf[NGX_QUIC_MAX_SR_PACKET];
u_char *token;
size_t len, max;
uint16_t rndbytes;
ngx_int_t rc;
u_char buf[NGX_QUIC_MAX_SR_PACKET];
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic handle stateless reset output");
@ -835,6 +837,11 @@ ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf,
return NGX_DECLINED;
}
rc = ngx_quic_stateless_reset_filter(c);
if (rc != NGX_OK) {
return rc;
}
if (pkt->len <= NGX_QUIC_MIN_SR_PACKET) {
len = pkt->len - 1;
@ -870,6 +877,56 @@ ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf,
}
static ngx_int_t
ngx_quic_stateless_reset_filter(ngx_connection_t *c)
{
time_t now;
u_char salt;
ngx_uint_t i, n, m, hit;
u_char hash[20];
static time_t t;
static u_char rndbyte;
static uint8_t bitmap[65536];
now = ngx_time();
if (t != now) {
t = now;
if (RAND_bytes(&rndbyte, 1) != 1) {
return NGX_ERROR;
}
ngx_memzero(bitmap, sizeof(bitmap));
}
hit = 0;
for (i = 0; i < 3; i++) {
salt = rndbyte + i;
ngx_quic_address_hash(c->sockaddr, c->socklen, 0, &salt, 1, hash);
n = hash[0] | hash[1] << 8;
m = 1 << hash[2] % 8;
if (!(bitmap[n] & m)) {
bitmap[n] |= m;
} else {
hit++;
}
}
if (hit == 3) {
return NGX_DECLINED;
}
return NGX_OK;
}
ngx_int_t
ngx_quic_send_cc(ngx_connection_t *c)
{

Loading…
Cancel
Save