nghttpx: Rate limit Stateless Reset transmission

This commit is contained in:
Tatsuhiro Tsujikawa 2021-09-05 19:23:50 +09:00
parent 67afbbbaa6
commit 85347e12de
3 changed files with 46 additions and 3 deletions

View File

@ -64,6 +64,7 @@ constexpr size_t SHRPX_QUIC_STATELESS_RESET_SECRETLEN = 32;
constexpr size_t SHRPX_QUIC_TOKEN_SECRETLEN = 32;
constexpr size_t SHRPX_QUIC_TOKEN_RAND_DATALEN = 16;
constexpr size_t SHRPX_QUIC_CONN_CLOSE_PKTLEN = 256;
constexpr size_t SHRPX_QUIC_STATELESS_RESET_BURST = 100;
// SHRPX_QUIC_RETRY_TOKEN_MAGIC is the magic byte of Retry token.
// Sent in plaintext.

View File

@ -37,10 +37,26 @@
namespace shrpx {
QUICConnectionHandler::QUICConnectionHandler(Worker *worker)
: worker_{worker} {}
namespace {
void stateless_reset_bucket_regen_timercb(struct ev_loop *loop, ev_timer *w,
int revents) {
auto quic_conn_handler = static_cast<QUICConnectionHandler *>(w->data);
QUICConnectionHandler::~QUICConnectionHandler() {}
quic_conn_handler->on_stateless_reset_bucket_regen();
}
} // namespace
QUICConnectionHandler::QUICConnectionHandler(Worker *worker)
: worker_{worker},
stateless_reset_bucket_{SHRPX_QUIC_STATELESS_RESET_BURST} {
ev_timer_init(&stateless_reset_bucket_regen_timer_,
stateless_reset_bucket_regen_timercb, 0., 1.);
stateless_reset_bucket_regen_timer_.data = this;
}
QUICConnectionHandler::~QUICConnectionHandler() {
ev_timer_stop(worker_->get_loop(), &stateless_reset_bucket_regen_timer_);
}
int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr,
const Address &remote_addr,
@ -378,6 +394,20 @@ int QUICConnectionHandler::send_stateless_reset(const UpstreamAddr *faddr,
size_t dcidlen,
const Address &remote_addr,
const Address &local_addr) {
if (stateless_reset_bucket_ == 0) {
if (LOG_ENABLED(INFO)) {
LOG(INFO) << "Stateless Reset bucket has been depleted";
}
return 0;
}
--stateless_reset_bucket_;
if (!ev_is_active(&stateless_reset_bucket_regen_timer_)) {
ev_timer_again(worker_->get_loop(), &stateless_reset_bucket_regen_timer_);
}
int rv;
std::array<uint8_t, NGTCP2_STATELESS_RESET_TOKENLEN> token;
ngtcp2_cid cid;
@ -469,6 +499,14 @@ void QUICConnectionHandler::remove_close_wait(const CloseWait *cw) {
}
}
void QUICConnectionHandler::on_stateless_reset_bucket_regen() {
assert(stateless_reset_bucket_ < SHRPX_QUIC_STATELESS_RESET_BURST);
if (++stateless_reset_bucket_ == SHRPX_QUIC_STATELESS_RESET_BURST) {
ev_timer_stop(worker_->get_loop(), &stateless_reset_bucket_regen_timer_);
}
}
static void close_wait_timeoutcb(struct ev_loop *loop, ev_timer *w,
int revents) {
auto cw = static_cast<CloseWait *>(w->data);

View File

@ -126,10 +126,14 @@ public:
void add_close_wait(CloseWait *cw);
void remove_close_wait(const CloseWait *cw);
void on_stateless_reset_bucket_regen();
private:
Worker *worker_;
std::unordered_map<ngtcp2_cid, ClientHandler *> connections_;
std::unordered_map<ngtcp2_cid, CloseWait *> close_waits_;
ev_timer stateless_reset_bucket_regen_timer_;
size_t stateless_reset_bucket_;
};
} // namespace shrpx