diff --git a/gennghttpxfun.py b/gennghttpxfun.py index fecfafd5..e0d36391 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -171,6 +171,7 @@ OPTIONS = [ "verify-client-tolerate-expired", "ignore-per-pattern-mruby-error", "tls-postpone-early-data", + "tls-max-early-data", ] LOGVARS = [ diff --git a/src/shrpx.cc b/src/shrpx.cc index 671adb65..52a7b2af 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -1465,6 +1465,7 @@ void fill_default_config(Config *config) { tls::proto_version_from_string(DEFAULT_TLS_MIN_PROTO_VERSION); tlsconf.max_proto_version = tls::proto_version_from_string(DEFAULT_TLS_MAX_PROTO_VERSION); + tlsconf.max_early_data = 16_k; #if OPENSSL_1_1_API || defined(OPENSSL_IS_BORINGSSL) tlsconf.ecdh_curves = StringRef::from_lit("X25519:P-256:P-384:P-521"); #else // !OPENSSL_1_1_API && !defined(OPENSSL_IS_BORINGSSL) @@ -2376,6 +2377,11 @@ SSL/TLS: handshake finishes. This option must be used to mitigate possible replay attack unless all backend servers recognize "Early-Data" header field. + --tls-max-early-data= + Sets the maximum amount of 0-RTT data that server + accepts. + Default: )" + << util::utos_unit(config->tls.max_early_data) << R"( HTTP/2: -c, --frontend-http2-max-concurrent-streams= @@ -3443,6 +3449,7 @@ int main(int argc, char **argv) { {SHRPX_OPT_IGNORE_PER_PATTERN_MRUBY_ERROR.c_str(), no_argument, &flag, 161}, {SHRPX_OPT_TLS_POSTPONE_EARLY_DATA.c_str(), no_argument, &flag, 162}, + {SHRPX_OPT_TLS_MAX_EARLY_DATA.c_str(), required_argument, &flag, 163}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -4219,6 +4226,10 @@ int main(int argc, char **argv) { cmdcfgs.emplace_back(SHRPX_OPT_TLS_POSTPONE_EARLY_DATA, StringRef::from_lit("yes")); break; + case 163: + // --tls-max-early-data + cmdcfgs.emplace_back(SHRPX_OPT_TLS_MAX_EARLY_DATA, StringRef{optarg}); + break; default: break; } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index e3675dc9..ddf2abdc 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -1883,6 +1883,11 @@ int option_lookup_token(const char *name, size_t namelen) { break; case 18: switch (name[17]) { + case 'a': + if (util::strieq_l("tls-max-early-dat", name, 17)) { + return SHRPX_OPTID_TLS_MAX_EARLY_DATA; + } + break; case 'r': if (util::strieq_l("add-request-heade", name, 17)) { return SHRPX_OPTID_ADD_REQUEST_HEADER; @@ -3600,6 +3605,9 @@ int parse_config(Config *config, int optid, const StringRef &opt, config->tls.postpone_early_data = util::strieq_l("yes", optarg); return 0; + case SHRPX_OPTID_TLS_MAX_EARLY_DATA: { + return parse_uint_with_unit(&config->tls.max_early_data, opt, optarg); + } case SHRPX_OPTID_CONF: LOG(WARN) << "conf: ignored"; diff --git a/src/shrpx_config.h b/src/shrpx_config.h index f2fc4511..c8987974 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -349,6 +349,8 @@ constexpr auto SHRPX_OPT_IGNORE_PER_PATTERN_MRUBY_ERROR = StringRef::from_lit("ignore-per-pattern-mruby-error"); constexpr auto SHRPX_OPT_TLS_POSTPONE_EARLY_DATA = StringRef::from_lit("tls-postpone-early-data"); +constexpr auto SHRPX_OPT_TLS_MAX_EARLY_DATA = + StringRef::from_lit("tls-max-early-data"); constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; @@ -652,6 +654,8 @@ struct TLSConfig { StringRef ciphers; StringRef ecdh_curves; StringRef cacert; + // The maximum amount of 0-RTT data that server accepts. + uint32_t max_early_data; // The minimum and maximum TLS version. These values are defined in // OpenSSL header file. int min_proto_version; @@ -1119,6 +1123,7 @@ enum { SHRPX_OPTID_SYSLOG_FACILITY, SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT, SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD, + SHRPX_OPTID_TLS_MAX_EARLY_DATA, SHRPX_OPTID_TLS_MAX_PROTO_VERSION, SHRPX_OPTID_TLS_MIN_PROTO_VERSION, SHRPX_OPTID_TLS_POSTPONE_EARLY_DATA, diff --git a/src/shrpx_tls.cc b/src/shrpx_tls.cc index bbfd6cfc..1b701fdf 100644 --- a/src/shrpx_tls.cc +++ b/src/shrpx_tls.cc @@ -973,6 +973,14 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file, } #endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L +#if OPENSSL_1_1_1_API + if (SSL_CTX_set_max_early_data(ssl_ctx, tlsconf.max_early_data) != 1) { + LOG(FATAL) << "SSL_CTX_set_max_early_data failed: " + << ERR_error_string(ERR_get_error(), nullptr); + DIE(); + } +#endif // OPENSSL_1_1_1_API + #ifndef OPENSSL_NO_PSK SSL_CTX_set_psk_server_callback(ssl_ctx, psk_server_cb); #endif // !LIBRESSL_NO_PSK