nghttpx: Implement TLSv1.3 0-RTT anti-replay with ClientHello cache

This commit is contained in:
Tatsuhiro Tsujikawa 2017-05-10 21:12:12 +09:00
parent b71d9ea58e
commit 8c6612d338
10 changed files with 375 additions and 13 deletions

View File

@ -168,6 +168,10 @@ OPTIONS = [
"no-strip-incoming-x-forwarded-proto",
"ocsp-startup",
"no-verify-ocsp",
"tls-anti-replay-memcached",
"tls-anti-replay-memcached-cert-file",
"tls-anti-replay-memcached-private-key-file",
"tls-anti-replay-memcached-address-family",
]
LOGVARS = [

View File

@ -1438,6 +1438,12 @@ void fill_default_config(Config *config) {
memcachedconf.family = AF_UNSPEC;
}
auto &anti_replayconf = tlsconf.anti_replay;
{
auto &memcachedconf = anti_replayconf.memcached;
memcachedconf.family = AF_UNSPEC;
}
ticketconf.cipher = EVP_aes_128_cbc();
}
@ -2284,6 +2290,25 @@ SSL/TLS:
--tls-session-cache-memcached-private-key-file=<PATH>
Path to client private key for memcached connections to
store session cache.
--tls-anti-replay-memcached=<HOST>,<PORT>[;tls]
Specify address of memcached server to store ClientHello
to avoid 0-RTT early data replay. This enables shared
storage between multiple nghttpx instances. Optionally,
memcached connection can be encrypted with TLS by
specifying "tls" parameter.
--tls-anti-replay-memcached-address-family=(auto|IPv4|IPv6)
Specify address family of memcached connections to store
ClientHello to avoid 0-RTT early data replay. If "auto"
is given, both IPv4 and IPv6 are considered. If "IPv4"
is given, only IPv4 address is considered. If "IPv6" is
given, only IPv6 address is considered.
Default: auto
--tls-anti-replay-memcached-cert-file=<PATH>
Path to client certificate for memcached connections to
store ClientHello to avoid 0-RTT early data replay.
--tls-anti-replay-memcached-private-key-file=<PATH>
Path to client private key for memcached connections to
store ClientHello to avoid 0-RTT early data replay.
--tls-dyn-rec-warmup-threshold=<SIZE>
Specify the threshold size for TLS dynamic record size
behaviour. During a TLS session, after the threshold
@ -2995,6 +3020,26 @@ int process_options(Config *config,
}
}
{
auto &memcachedconf = tlsconf.anti_replay.memcached;
if (!memcachedconf.host.empty()) {
auto hostport = util::make_hostport(StringRef{memcachedconf.host},
memcachedconf.port);
if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.c_str(),
memcachedconf.port, memcachedconf.family) == -1) {
LOG(FATAL) << "Resolving memcached address for TLS anti-replay failed: "
<< hostport;
return -1;
}
LOG(NOTICE) << "Memcached address for TLS anti-replay: " << hostport
<< " -> " << util::to_numeric_addr(&memcachedconf.addr);
if (memcachedconf.tls) {
LOG(NOTICE) << "Connection to memcached for TLS anti-replay will be "
"encrypted by TLS";
}
}
}
if (config->rlimit_nofile) {
struct rlimit lim = {static_cast<rlim_t>(config->rlimit_nofile),
static_cast<rlim_t>(config->rlimit_nofile)};
@ -3404,6 +3449,14 @@ int main(int argc, char **argv) {
{SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO.c_str(), no_argument,
&flag, 158},
{SHRPX_OPT_SINGLE_PROCESS.c_str(), no_argument, &flag, 159},
{SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED.c_str(), required_argument, &flag,
160},
{SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_ADDRESS_FAMILY.c_str(),
required_argument, &flag, 161},
{SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_CERT_FILE.c_str(),
required_argument, &flag, 162},
{SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_PRIVATE_KEY_FILE.c_str(),
required_argument, &flag, 163},
{nullptr, 0, nullptr, 0}};
int option_index = 0;
@ -4165,6 +4218,27 @@ int main(int argc, char **argv) {
cmdcfgs.emplace_back(SHRPX_OPT_SINGLE_PROCESS,
StringRef::from_lit("yes"));
break;
case 160:
// --tls-anti-replay-memcached
cmdcfgs.emplace_back(SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED,
StringRef{optarg});
break;
case 161:
// --tls-anti-replay-memcached-address-family
cmdcfgs.emplace_back(SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_ADDRESS_FAMILY,
StringRef{optarg});
break;
case 162:
// --tls-anti-replay-memcached-cert-file
cmdcfgs.emplace_back(SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_CERT_FILE,
StringRef{optarg});
break;
case 163:
// --tls-anti-replay-memcached-private-key-file
cmdcfgs.emplace_back(
SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_PRIVATE_KEY_FILE,
StringRef{optarg});
break;
default:
break;
}

View File

@ -2072,6 +2072,11 @@ int option_lookup_token(const char *name, size_t namelen) {
break;
case 25:
switch (name[24]) {
case 'd':
if (util::strieq_l("tls-anti-replay-memcache", name, 24)) {
return SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED;
}
break;
case 'e':
if (util::strieq_l("backend-http2-window-siz", name, 24)) {
return SHRPX_OPTID_BACKEND_HTTP2_WINDOW_SIZE;
@ -2255,6 +2260,9 @@ int option_lookup_token(const char *name, size_t namelen) {
if (util::strieq_l("frontend-http2-optimize-window-siz", name, 34)) {
return SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE;
}
if (util::strieq_l("tls-anti-replay-memcached-cert-fil", name, 34)) {
return SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED_CERT_FILE;
}
break;
case 'o':
if (util::strieq_l("no-strip-incoming-x-forwarded-prot", name, 34)) {
@ -2338,6 +2346,11 @@ int option_lookup_token(const char *name, size_t namelen) {
return SHRPX_OPTID_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE;
}
break;
case 'y':
if (util::strieq_l("tls-anti-replay-memcached-address-famil", name, 39)) {
return SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED_ADDRESS_FAMILY;
}
break;
}
break;
case 41:
@ -2364,6 +2377,12 @@ int option_lookup_token(const char *name, size_t namelen) {
break;
case 42:
switch (name[41]) {
case 'e':
if (util::strieq_l("tls-anti-replay-memcached-private-key-fil", name,
41)) {
return SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED_PRIVATE_KEY_FILE;
}
break;
case 'y':
if (util::strieq_l("tls-session-cache-memcached-address-famil", name,
41)) {
@ -3153,7 +3172,8 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return 0;
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED:
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: {
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED:
case SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED: {
auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';');
auto src_params = StringRef{addr_end, std::end(optarg)};
@ -3183,6 +3203,13 @@ int parse_config(Config *config, int optid, const StringRef &opt,
memcachedconf.tls = params.tls;
break;
}
case SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED: {
auto &memcachedconf = config->tls.anti_replay.memcached;
memcachedconf.host = make_string_ref(config->balloc, StringRef{host});
memcachedconf.port = port;
memcachedconf.tls = params.tls;
break;
}
};
return 0;
@ -3330,6 +3357,16 @@ int parse_config(Config *config, int optid, const StringRef &opt,
config->tls.ticket.memcached.private_key_file =
make_string_ref(config->balloc, optarg);
return 0;
case SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED_CERT_FILE:
config->tls.anti_replay.memcached.cert_file =
make_string_ref(config->balloc, optarg);
return 0;
case SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED_PRIVATE_KEY_FILE:
config->tls.anti_replay.memcached.private_key_file =
make_string_ref(config->balloc, optarg);
return 0;
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY:
return parse_address_family(&config->tls.ticket.memcached.family, opt,
@ -3337,6 +3374,9 @@ int parse_config(Config *config, int optid, const StringRef &opt,
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY:
return parse_address_family(&config->tls.session_cache.memcached.family,
opt, optarg);
case SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED_ADDRESS_FAMILY:
return parse_address_family(&config->tls.anti_replay.memcached.family, opt,
optarg);
case SHRPX_OPTID_BACKEND_ADDRESS_FAMILY:
return parse_address_family(&config->conn.downstream->family, opt, optarg);
case SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS:

View File

@ -343,6 +343,14 @@ constexpr auto SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO =
StringRef::from_lit("no-strip-incoming-x-forwarded-proto");
constexpr auto SHRPX_OPT_OCSP_STARTUP = StringRef::from_lit("ocsp-startup");
constexpr auto SHRPX_OPT_NO_VERIFY_OCSP = StringRef::from_lit("no-verify-ocsp");
constexpr auto SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED =
StringRef::from_lit("tls-anti-replay-memcached");
constexpr auto SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_CERT_FILE =
StringRef::from_lit("tls-anti-replay-memcached-cert-file");
constexpr auto SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_PRIVATE_KEY_FILE =
StringRef::from_lit("tls-anti-replay-memcached-private-key-file");
constexpr auto SHRPX_OPT_TLS_ANTI_REPLAY_MEMCACHED_ADDRESS_FAMILY =
StringRef::from_lit("tls-anti-replay-memcached-address-family");
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
@ -577,6 +585,23 @@ struct TLSConfig {
} memcached;
} session_cache;
struct {
struct {
Address addr;
uint16_t port;
// Hostname of memcached server. This is also used as SNI field
// if TLS is enabled.
StringRef host;
// Client private key and certificate for authentication
StringRef private_key_file;
StringRef cert_file;
// Address family of memcached connection. One of either
// AF_INET, AF_INET6 or AF_UNSPEC.
int family;
bool tls;
} memcached;
} anti_replay;
// Dynamic record sizing configurations
struct {
size_t warmup_threshold;
@ -1097,6 +1122,10 @@ enum {
SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR,
SHRPX_OPTID_SUBCERT,
SHRPX_OPTID_SYSLOG_FACILITY,
SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED,
SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED_ADDRESS_FAMILY,
SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED_CERT_FILE,
SHRPX_OPTID_TLS_ANTI_REPLAY_MEMCACHED_PRIVATE_KEY_FILE,
SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT,
SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD,
SHRPX_OPTID_TLS_MAX_PROTO_VERSION,

View File

@ -38,7 +38,6 @@
#include "shrpx_log.h"
#include "memchunk.h"
#include "util.h"
#include "ssl_compat.h"
using namespace nghttp2;
@ -93,7 +92,15 @@ Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl,
}
}
Connection::~Connection() { disconnect(); }
Connection::~Connection() {
disconnect();
#if OPENSSL_1_1_1_API
if (tls.ch_md_ctx) {
EVP_MD_CTX_free(tls.ch_md_ctx);
}
#endif // OPENSSL_1_1_1_API
}
void Connection::disconnect() {
if (tls.ssl) {
@ -111,10 +118,21 @@ void Connection::disconnect() {
tls.cached_session_lookup_req = nullptr;
}
if (tls.anti_replay_req) {
tls.anti_replay_req->canceled = true;
tls.anti_replay_req = nullptr;
}
SSL_shutdown(tls.ssl);
SSL_free(tls.ssl);
tls.ssl = nullptr;
#if OPENSSL_1_1_1_API
if (tls.ch_md_ctx) {
EVP_MD_CTX_reset(tls.ch_md_ctx);
}
#endif // OPENSSL_1_1_1_API
tls.wbuf.reset();
tls.rbuf.reset();
tls.last_write_idle = 0.;
@ -126,6 +144,7 @@ void Connection::disconnect() {
tls.reneg_started = false;
tls.sct_requested = false;
tls.early_data_finish = false;
tls.early_cb_called = false;
}
if (fd != -1) {
@ -152,6 +171,14 @@ void Connection::prepare_client_handshake() {
void Connection::prepare_server_handshake() {
SSL_set_accept_state(tls.ssl);
tls.server_handshake = true;
#if OPENSSL_1_1_1_API
if (!tls.ch_md_ctx) {
tls.ch_md_ctx = EVP_MD_CTX_new();
}
EVP_DigestInit_ex(tls.ch_md_ctx, EVP_sha256(), nullptr);
#endif // OPENSSL_1_1_1_API
}
// BIO implementation is inspired by openldap implementation:
@ -225,7 +252,19 @@ int shrpx_bio_read(BIO *b, char *buf, int len) {
return -1;
}
return rbuf.remove(buf, len);
len = rbuf.remove(buf, len);
if (conn->tls.early_cb_called) {
return len;
}
#if OPENSSL_1_1_1_API
if (EVP_DigestUpdate(conn->tls.ch_md_ctx, buf, len) == 0) {
return -1;
}
#endif // OPENSSL_1_1_1_API
return len;
}
} // namespace
@ -355,6 +394,7 @@ int Connection::tls_handshake() {
switch (tls.handshake_state) {
case TLS_CONN_WAIT_FOR_SESSION_CACHE:
case TLS_CONN_WAIT_FOR_ANTI_REPLAY:
return SHRPX_ERR_INPROGRESS;
case TLS_CONN_GOT_SESSION_CACHE: {
// Use the same trick invented by @kazuho in h2o project.
@ -401,15 +441,27 @@ int Connection::tls_handshake() {
rv = SSL_read_early_data(tls.ssl, buf.data(), buf.size(), &nread);
if (rv == SSL_READ_EARLY_DATA_ERROR) {
if (SSL_get_error(tls.ssl, rv) == SSL_ERROR_WANT_EARLY) {
if (LOG_ENABLED(INFO)) {
LOG(INFO)
<< "tls: early_cb returns negative return value; handshake "
"interrupted";
}
break;
}
// If we have early data, and server sends ServerHello, assume
// that handshake is completed in server side, and start
// processing request. If we don't exit handshake code here,
// server waits for EndOfEarlyData and Finished message from
// client, which voids the purpose of 0-RTT data. The left
// over of handshake is done through write_tls or read_tls.
rv = (tls.handshake_state == TLS_CONN_WRITE_STARTED ||
tls.wbuf.rleft()) &&
tls.earlybuf.rleft();
if ((tls.handshake_state == TLS_CONN_WRITE_STARTED ||
tls.wbuf.rleft()) &&
tls.earlybuf.rleft()) {
rv = 1;
}
break;
}
@ -454,6 +506,9 @@ int Connection::tls_handshake() {
}
break;
case SSL_ERROR_WANT_WRITE:
#if OPENSSL_1_1_1_API
case SSL_ERROR_WANT_EARLY:
#endif // OPENSSL_1_1_1_API
break;
case SSL_ERROR_SSL:
if (LOG_ENABLED(INFO)) {
@ -469,7 +524,8 @@ int Connection::tls_handshake() {
}
}
if (tls.handshake_state == TLS_CONN_WAIT_FOR_SESSION_CACHE) {
if (tls.handshake_state == TLS_CONN_WAIT_FOR_SESSION_CACHE ||
tls.handshake_state == TLS_CONN_WAIT_FOR_ANTI_REPLAY) {
if (LOG_ENABLED(INFO)) {
LOG(INFO) << "tls: handshake is still in progress";
}

View File

@ -32,10 +32,12 @@
#include <ev.h>
#include <openssl/ssl.h>
#include <openssl/evp.h>
#include "shrpx_rate_limit.h"
#include "shrpx_error.h"
#include "memchunk.h"
#include "ssl_compat.h"
namespace shrpx {
@ -50,6 +52,7 @@ enum {
TLS_CONN_WAIT_FOR_SESSION_CACHE,
TLS_CONN_GOT_SESSION_CACHE,
TLS_CONN_CANCEL_SESSION_CACHE,
TLS_CONN_WAIT_FOR_ANTI_REPLAY,
TLS_CONN_WRITE_STARTED,
};
@ -62,6 +65,11 @@ struct TLSConnection {
SSL_SESSION *cached_session;
MemcachedRequest *cached_session_lookup_req;
tls::TLSSessionCache *client_session_cache;
#if OPENSSL_1_1_1_API
// Message digest context to calculate ClientHello for anti-replay.
EVP_MD_CTX *ch_md_ctx;
#endif // !OPENSSL_1_1_1_API
MemcachedRequest *anti_replay_req;
ev_tstamp last_write_idle;
size_t warmup_writelen;
// length passed to SSL_write and SSL_read last time. This is
@ -82,6 +90,8 @@ struct TLSConnection {
// This value is also true if this is client side connection for
// convenience.
bool early_data_finish;
// true if early_cb gets called.
bool early_cb_called;
};
struct TCPHint {

View File

@ -235,9 +235,24 @@ int ConnectionHandler::create_single_worker() {
}
}
SSL_CTX *anti_replay_ssl_ctx = nullptr;
{
auto &memcachedconf = config->tls.anti_replay.memcached;
if (memcachedconf.tls) {
anti_replay_ssl_ctx = tls::create_ssl_client_context(
#ifdef HAVE_NEVERBLEED
nb_.get(),
#endif // HAVE_NEVERBLEED
tlsconf.cacert, memcachedconf.cert_file,
memcachedconf.private_key_file, nullptr);
all_ssl_ctx_.push_back(anti_replay_ssl_ctx);
}
}
single_worker_ = make_unique<Worker>(
loop_, sv_ssl_ctx, cl_ssl_ctx, session_cache_ssl_ctx, cert_tree_.get(),
ticket_keys_, this, config->conn.downstream);
loop_, sv_ssl_ctx, cl_ssl_ctx, session_cache_ssl_ctx, anti_replay_ssl_ctx,
cert_tree_.get(), ticket_keys_, this, config->conn.downstream);
#ifdef HAVE_MRUBY
if (single_worker_->create_mruby_context() != 0) {
return -1;
@ -293,12 +308,28 @@ int ConnectionHandler::create_worker_thread(size_t num) {
}
}
SSL_CTX *anti_replay_ssl_ctx = nullptr;
{
auto &memcachedconf = config->tls.anti_replay.memcached;
if (memcachedconf.tls) {
anti_replay_ssl_ctx = tls::create_ssl_client_context(
#ifdef HAVE_NEVERBLEED
nb_.get(),
#endif // HAVE_NEVERBLEED
tlsconf.cacert, memcachedconf.cert_file,
memcachedconf.private_key_file, nullptr);
all_ssl_ctx_.push_back(anti_replay_ssl_ctx);
}
}
for (size_t i = 0; i < num; ++i) {
auto loop = ev_loop_new(config->ev_loop_flags);
auto worker = make_unique<Worker>(
loop, sv_ssl_ctx, cl_ssl_ctx, session_cache_ssl_ctx, cert_tree_.get(),
ticket_keys_, this, config->conn.downstream);
auto worker =
make_unique<Worker>(loop, sv_ssl_ctx, cl_ssl_ctx, session_cache_ssl_ctx,
anti_replay_ssl_ctx, cert_tree_.get(), ticket_keys_,
this, config->conn.downstream);
#ifdef HAVE_MRUBY
if (worker->create_mruby_context() != 0) {
return -1;

View File

@ -534,6 +534,103 @@ void info_callback(const SSL *ssl, int where, int ret) {
}
} // namespace
#if OPENSSL_1_1_1_API
constexpr auto MEMCACHED_ANTI_REPLY_KEY_PREFIX =
StringRef::from_lit("nghttpx:anti-reply:");
namespace {
int early_cb(SSL *ssl, int *al, void *arg) {
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
if (conn->tls.early_cb_called) {
return 1;
}
conn->tls.early_cb_called = true;
const unsigned char *ext;
size_t extlen;
if (!SSL_early_get0_ext(conn->tls.ssl, TLSEXT_TYPE_early_data, &ext,
&extlen)) {
if (LOG_ENABLED(INFO)) {
LOG(INFO) << "early_data extension does not exist";
}
return 1;
}
if (!SSL_early_get0_ext(conn->tls.ssl, TLSEXT_TYPE_psk, &ext, &extlen)) {
if (LOG_ENABLED(INFO)) {
LOG(INFO) << "pre_shared_key extension does not exist";
}
return 1;
}
std::array<uint8_t, 32> md;
unsigned int mdlen;
if (EVP_DigestFinal_ex(conn->tls.ch_md_ctx, md.data(), &mdlen) == 0) {
LOG(ERROR) << "EVP_DigestFinal_ex failed";
return 0;
}
assert(md.size() == mdlen);
auto handler = static_cast<ClientHandler *>(conn->data);
auto worker = handler->get_worker();
auto dispatcher = worker->get_anti_replay_memcached_dispatcher();
auto &balloc = handler->get_block_allocator();
auto &tlsconf = get_config()->tls;
auto hex_md =
util::format_hex(balloc, StringRef{std::begin(md), std::end(md)});
if (tlsconf.anti_replay.memcached.host.empty()) {
return 1;
}
auto req = make_unique<MemcachedRequest>();
req->op = MEMCACHED_OP_ADD;
req->key = MEMCACHED_ANTI_REPLY_KEY_PREFIX.str();
req->key += hex_md;
// TODO No value at the moment
// Set the same timeout value for session with the hope that
// OpenSSL library invalidates the outdated ticket.
req->expiry = tlsconf.session_timeout.count();
req->cb = [conn](MemcachedRequest *req, MemcachedResult res) {
if (LOG_ENABLED(INFO)) {
LOG(INFO) << "Memcached: ClientHello anti-replay registration done. key="
<< req->key << ", status_code=" << res.status_code;
}
// We might stop reading, so start it again
conn->rlimit.startw();
ev_timer_again(conn->loop, &conn->rt);
conn->wlimit.startw();
ev_timer_again(conn->loop, &conn->wt);
conn->tls.anti_replay_req = nullptr;
if (res.status_code != 0) {
// If we cannot add key/value, just disable 0-RTT early data.
// Note that memcached atomically adds key/value.
conn->tls.early_data_finish = true;
}
conn->tls.handshake_state = TLS_CONN_NORMAL;
};
conn->tls.handshake_state = TLS_CONN_WAIT_FOR_ANTI_REPLAY;
conn->tls.anti_replay_req = req.get();
dispatcher->add_request(std::move(req));
return -1;
}
} // namespace
#endif // OPENSSL_1_1_1_API
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
namespace {
int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
@ -920,6 +1017,10 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
#endif // OPENSSL_IS_BORINGSSL
SSL_CTX_set_info_callback(ssl_ctx, info_callback);
#if OPENSSL_1_1_1_API
SSL_CTX_set_early_cb(ssl_ctx, early_cb, nullptr);
#endif // OPENSSL_1_1_1_API
#ifdef OPENSSL_IS_BORINGSSL
SSL_CTX_set_early_data_enabled(ssl_ctx, 1);
#endif // OPENSSL_IS_BORINGSSL

View File

@ -118,6 +118,7 @@ bool match_shared_downstream_addr(
Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
SSL_CTX *tls_session_cache_memcached_ssl_ctx,
SSL_CTX *tls_anti_replay_memcached_ssl_ctx,
tls::CertLookupTree *cert_tree,
const std::shared_ptr<TicketKeys> &ticket_keys,
ConnectionHandler *conn_handler,
@ -153,6 +154,15 @@ Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
StringRef{session_cacheconf.memcached.host}, &mcpool_, randgen_);
}
auto &anti_replayconf = get_config()->tls.anti_replay;
if (!anti_replayconf.memcached.host.empty()) {
anti_replay_memcached_dispatcher_ = make_unique<MemcachedDispatcher>(
&anti_replayconf.memcached.addr, loop,
tls_anti_replay_memcached_ssl_ctx, anti_replayconf.memcached.host,
&mcpool_, randgen_);
}
replace_downstream_config(std::move(downstreamconf));
}
@ -474,6 +484,10 @@ MemcachedDispatcher *Worker::get_session_cache_memcached_dispatcher() {
return session_cache_memcached_dispatcher_.get();
}
MemcachedDispatcher *Worker::get_anti_replay_memcached_dispatcher() const {
return anti_replay_memcached_dispatcher_.get();
}
std::mt19937 &Worker::get_randgen() { return randgen_; }
#ifdef HAVE_MRUBY

View File

@ -221,6 +221,7 @@ class Worker {
public:
Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
SSL_CTX *tls_session_cache_memcached_ssl_ctx,
SSL_CTX *tls_anti_replay_memcached_ssl_ctx,
tls::CertLookupTree *cert_tree,
const std::shared_ptr<TicketKeys> &ticket_keys,
ConnectionHandler *conn_handler,
@ -250,6 +251,7 @@ public:
void schedule_clear_mcpool();
MemcachedDispatcher *get_session_cache_memcached_dispatcher();
MemcachedDispatcher *get_anti_replay_memcached_dispatcher() const;
std::mt19937 &get_randgen();
@ -289,6 +291,7 @@ private:
std::shared_ptr<DownstreamConfig> downstreamconf_;
std::unique_ptr<MemcachedDispatcher> session_cache_memcached_dispatcher_;
std::unique_ptr<MemcachedDispatcher> anti_replay_memcached_dispatcher_;
#ifdef HAVE_MRUBY
std::unique_ptr<mruby::MRubyContext> mruby_ctx_;
#endif // HAVE_MRUBY