From 2f5ec66a650bb5f09bbccc8cfdaf47e3949b6c47 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 12 Mar 2022 19:42:19 +0900 Subject: [PATCH] nghttpx: Limit CONNECTION_CLOSE and Retry under server amplification limit --- src/shrpx_http3_upstream.cc | 4 ++-- src/shrpx_quic_connection_handler.cc | 26 +++++++++++++++----------- src/shrpx_quic_connection_handler.h | 6 ++++-- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/shrpx_http3_upstream.cc b/src/shrpx_http3_upstream.cc index d2036a53..86f18aee 100644 --- a/src/shrpx_http3_upstream.cc +++ b/src/shrpx_http3_upstream.cc @@ -1785,7 +1785,7 @@ int Http3Upstream::on_read(const UpstreamAddr *faddr, quic_conn_handler->send_connection_close( faddr, version, ini_dcid, ini_scid, remote_addr, local_addr, - NGTCP2_CONNECTION_REFUSED); + NGTCP2_CONNECTION_REFUSED, datalen * 3); return -1; } @@ -1794,7 +1794,7 @@ int Http3Upstream::on_read(const UpstreamAddr *faddr, quic_conn_handler->send_retry(handler_->get_upstream_addr(), version, dcid, dcidlen, scid, scidlen, remote_addr, - local_addr); + local_addr, datalen * 3); return -1; } diff --git a/src/shrpx_quic_connection_handler.cc b/src/shrpx_quic_connection_handler.cc index 955534ba..7a131b60 100644 --- a/src/shrpx_quic_connection_handler.cc +++ b/src/shrpx_quic_connection_handler.cc @@ -200,14 +200,15 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, if (worker_->get_graceful_shutdown()) { send_connection_close(faddr, version, hd.dcid, hd.scid, remote_addr, - local_addr, NGTCP2_CONNECTION_REFUSED); + local_addr, NGTCP2_CONNECTION_REFUSED, + datalen * 3); return 0; } if (hd.token.len == 0) { if (quicconf.upstream.require_token) { send_retry(faddr, version, dcid, dcidlen, scid, scidlen, remote_addr, - local_addr); + local_addr, datalen * 3); return 0; } @@ -235,7 +236,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, // 2nd Retry packet is not allowed, so send CONNECTION_CLOSE // with INVALID_TOKEN. send_connection_close(faddr, version, hd.dcid, hd.scid, remote_addr, - local_addr, NGTCP2_INVALID_TOKEN); + local_addr, NGTCP2_INVALID_TOKEN, datalen * 3); return 0; } @@ -260,7 +261,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, if (quicconf.upstream.require_token) { send_retry(faddr, version, dcid, dcidlen, scid, scidlen, - remote_addr, local_addr); + remote_addr, local_addr, datalen * 3); return 0; } @@ -280,7 +281,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, default: if (quicconf.upstream.require_token) { send_retry(faddr, version, dcid, dcidlen, scid, scidlen, remote_addr, - local_addr); + local_addr, datalen * 3); return 0; } @@ -293,12 +294,13 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, case NGTCP2_ERR_RETRY: if (worker_->get_graceful_shutdown()) { send_connection_close(faddr, version, hd.dcid, hd.scid, remote_addr, - local_addr, NGTCP2_CONNECTION_REFUSED); + local_addr, NGTCP2_CONNECTION_REFUSED, + datalen * 3); return 0; } send_retry(faddr, version, dcid, dcidlen, scid, scidlen, remote_addr, - local_addr); + local_addr, datalen * 3); return 0; case NGTCP2_ERR_VERSION_NEGOTIATION: send_version_negotiation(faddr, version, dcid, dcidlen, scid, scidlen, @@ -439,7 +441,7 @@ uint32_t generate_reserved_version(const Address &addr, uint32_t version) { int QUICConnectionHandler::send_retry( const UpstreamAddr *faddr, uint32_t version, const uint8_t *ini_dcid, size_t ini_dcidlen, const uint8_t *ini_scid, size_t ini_scidlen, - const Address &remote_addr, const Address &local_addr) { + const Address &remote_addr, const Address &local_addr, size_t max_pktlen) { std::array host; std::array port; @@ -478,7 +480,7 @@ int QUICConnectionHandler::send_retry( } std::vector buf; - buf.resize(256); + buf.resize(std::min(max_pktlen, static_cast(256))); auto nwrite = ngtcp2_crypto_write_retry(buf.data(), buf.size(), version, &iscid, @@ -611,11 +613,13 @@ int QUICConnectionHandler::send_stateless_reset(const UpstreamAddr *faddr, int QUICConnectionHandler::send_connection_close( const UpstreamAddr *faddr, uint32_t version, const ngtcp2_cid &ini_dcid, const ngtcp2_cid &ini_scid, const Address &remote_addr, - const Address &local_addr, uint64_t error_code) { + const Address &local_addr, uint64_t error_code, size_t max_pktlen) { std::array buf; + max_pktlen = std::min(max_pktlen, buf.size()); + auto nwrite = ngtcp2_crypto_write_connection_close( - buf.data(), buf.size(), version, &ini_scid, &ini_dcid, error_code, + buf.data(), max_pktlen, version, &ini_scid, &ini_dcid, error_code, nullptr, 0); if (nwrite < 0) { LOG(ERROR) << "ngtcp2_crypto_write_connection_close failed"; diff --git a/src/shrpx_quic_connection_handler.h b/src/shrpx_quic_connection_handler.h index 48faba77..da239cff 100644 --- a/src/shrpx_quic_connection_handler.h +++ b/src/shrpx_quic_connection_handler.h @@ -91,7 +91,8 @@ public: int send_retry(const UpstreamAddr *faddr, uint32_t version, const uint8_t *ini_dcid, size_t ini_dcidlen, const uint8_t *ini_scid, size_t ini_scidlen, - const Address &remote_addr, const Address &local_addr); + const Address &remote_addr, const Address &local_addr, + size_t max_pktlen); // Send Version Negotiation packet. |ini_dcid| is the destination // Connection ID which appeared in Client Initial packet and its // length is |dcidlen|. |ini_scid| is the source Connection ID @@ -113,7 +114,8 @@ public: const ngtcp2_cid &ini_dcid, const ngtcp2_cid &ini_scid, const Address &remote_addr, - const Address &local_addr, uint64_t error_code); + const Address &local_addr, uint64_t error_code, + size_t max_pktlen); ClientHandler *handle_new_connection(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr,