diff --git a/gennghttpxfun.py b/gennghttpxfun.py index 337c1cb4..988cb331 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -190,6 +190,7 @@ OPTIONS = [ "frontend-http3-max-concurrent-streams", "frontend-quic-early-data", "frontend-quic-qlog-dir", + "frontend-quic-require-token", ] LOGVARS = [ diff --git a/src/shrpx.cc b/src/shrpx.cc index 4938f5cf..15d11867 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -3222,6 +3222,10 @@ HTTP/3 and QUIC: each QUIC connection. The file name is ISO8601 basic format, followed by "-", server Source Connection ID and ".qlog". + --frontend-quic-require-token + Require an address validation token for a frontend QUIC + connection. Server sends a token in Retry packet or + NEW_TOKEN frame in the previous connection. --no-quic-bpf Disable eBPF. --frontend-http3-window-size= @@ -4011,6 +4015,8 @@ int main(int argc, char **argv) { {SHRPX_OPT_FRONTEND_QUIC_EARLY_DATA.c_str(), no_argument, &flag, 180}, {SHRPX_OPT_FRONTEND_QUIC_QLOG_DIR.c_str(), required_argument, &flag, 181}, + {SHRPX_OPT_FRONTEND_QUIC_REQUIRE_TOKEN.c_str(), no_argument, &flag, + 182}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -4878,6 +4884,11 @@ int main(int argc, char **argv) { cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_QUIC_QLOG_DIR, StringRef{optarg}); break; + case 182: + // --frontend-quic-require-token + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_QUIC_REQUIRE_TOKEN, + StringRef::from_lit("yes")); + break; default: break; } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 356c4bca..f07e48dd 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -2401,6 +2401,11 @@ int option_lookup_token(const char *name, size_t namelen) { return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED; } break; + case 'n': + if (util::strieq_l("frontend-quic-require-toke", name, 26)) { + return SHRPX_OPTID_FRONTEND_QUIC_REQUIRE_TOKEN; + } + break; case 'r': if (util::strieq_l("request-header-field-buffe", name, 26)) { return SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER; @@ -3986,6 +3991,12 @@ int parse_config(Config *config, int optid, const StringRef &opt, config->quic.upstream.qlog.dir = optarg; #endif // ENABLE_HTTP3 + return 0; + case SHRPX_OPTID_FRONTEND_QUIC_REQUIRE_TOKEN: +#ifdef ENABLE_HTTP3 + config->quic.upstream.require_token = util::strieq_l("yes", optarg); +#endif // ENABLE_HTTP3 + return 0; case SHRPX_OPTID_CONF: LOG(WARN) << "conf: ignored"; diff --git a/src/shrpx_config.h b/src/shrpx_config.h index fdb7bae0..6b781f38 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -387,6 +387,8 @@ constexpr auto SHRPX_OPT_FRONTEND_QUIC_EARLY_DATA = StringRef::from_lit("frontend-quic-early-data"); constexpr auto SHRPX_OPT_FRONTEND_QUIC_QLOG_DIR = StringRef::from_lit("frontend-quic-qlog-dir"); +constexpr auto SHRPX_OPT_FRONTEND_QUIC_REQUIRE_TOKEN = + StringRef::from_lit("frontend-quic-require-token"); constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; @@ -755,6 +757,7 @@ struct QUICConfig { StringRef dir; } qlog; bool early_data; + bool require_token; } upstream; struct { StringRef prog_file; @@ -1211,6 +1214,7 @@ enum { SHRPX_OPTID_FRONTEND_QUIC_EARLY_DATA, SHRPX_OPTID_FRONTEND_QUIC_IDLE_TIMEOUT, SHRPX_OPTID_FRONTEND_QUIC_QLOG_DIR, + SHRPX_OPTID_FRONTEND_QUIC_REQUIRE_TOKEN, SHRPX_OPTID_FRONTEND_READ_TIMEOUT, SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT, SHRPX_OPTID_HEADER_FIELD_BUFFER, diff --git a/src/shrpx_quic_connection_handler.cc b/src/shrpx_quic_connection_handler.cc index f7341913..0f3590e0 100644 --- a/src/shrpx_quic_connection_handler.cc +++ b/src/shrpx_quic_connection_handler.cc @@ -134,6 +134,8 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, const uint8_t *token = nullptr; size_t tokenlen = 0; + auto &quicconf = config->quic; + switch (ngtcp2_accept(&hd, data, datalen)) { case 0: { // If we get Initial and it has the CID prefix of this worker, it @@ -145,6 +147,13 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, } if (hd.token.len == 0) { + if (quicconf.upstream.require_token) { + send_retry(faddr, version, dcid, dcidlen, scid, scidlen, remote_addr, + local_addr); + + return 0; + } + break; } @@ -186,6 +195,13 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, << util::to_numeric_addr(&remote_addr); } + if (quicconf.upstream.require_token) { + send_retry(faddr, version, dcid, dcidlen, scid, scidlen, + remote_addr, local_addr); + + return 0; + } + break; } @@ -199,6 +215,13 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, break; default: + if (quicconf.upstream.require_token) { + send_retry(faddr, version, dcid, dcidlen, scid, scidlen, remote_addr, + local_addr); + + return 0; + } + break; }