nghttpx: Add client auth options for session cache memcached TLS connection
This commit is contained in:
parent
f1580f95d4
commit
3297a303bf
|
@ -115,7 +115,9 @@ OPTIONS = [
|
||||||
"max-header-fields",
|
"max-header-fields",
|
||||||
"no-http2-cipher-black-list",
|
"no-http2-cipher-black-list",
|
||||||
"backend-http1-tls",
|
"backend-http1-tls",
|
||||||
"backend-tls-session-cache-per-worker"
|
"backend-tls-session-cache-per-worker",
|
||||||
|
"tls-session-cache-memcached-cert-file",
|
||||||
|
"tls-session-cache-memcached-private-key-file"
|
||||||
]
|
]
|
||||||
|
|
||||||
LOGVARS = [
|
LOGVARS = [
|
||||||
|
|
20
src/shrpx.cc
20
src/shrpx.cc
|
@ -1567,6 +1567,12 @@ SSL/TLS:
|
||||||
--tls-session-cache-memcached-tls
|
--tls-session-cache-memcached-tls
|
||||||
Enable SSL/TLS on memcached connections to store session
|
Enable SSL/TLS on memcached connections to store session
|
||||||
cache.
|
cache.
|
||||||
|
--tls-session-cache-memcached-cert-file=<PATH>
|
||||||
|
Path to client certificate for memcached connections to
|
||||||
|
store session cache.
|
||||||
|
--tls-session-cache-memcached-private-key-file=<PATH>
|
||||||
|
Path to client private key for memcached connections to
|
||||||
|
store session cache.
|
||||||
--tls-dyn-rec-warmup-threshold=<SIZE>
|
--tls-dyn-rec-warmup-threshold=<SIZE>
|
||||||
Specify the threshold size for TLS dynamic record size
|
Specify the threshold size for TLS dynamic record size
|
||||||
behaviour. During a TLS session, after the threshold
|
behaviour. During a TLS session, after the threshold
|
||||||
|
@ -2404,6 +2410,10 @@ int main(int argc, char **argv) {
|
||||||
{SHRPX_OPT_BACKEND_TLS_SESSION_CACHE_PER_WORKER, required_argument,
|
{SHRPX_OPT_BACKEND_TLS_SESSION_CACHE_PER_WORKER, required_argument,
|
||||||
&flag, 107},
|
&flag, 107},
|
||||||
{SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS, no_argument, &flag, 108},
|
{SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS, no_argument, &flag, 108},
|
||||||
|
{SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE, required_argument,
|
||||||
|
&flag, 109},
|
||||||
|
{SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE,
|
||||||
|
required_argument, &flag, 110},
|
||||||
{nullptr, 0, nullptr, 0}};
|
{nullptr, 0, nullptr, 0}};
|
||||||
|
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
@ -2866,6 +2876,16 @@ int main(int argc, char **argv) {
|
||||||
// --tls-session-cache-memcached-tls
|
// --tls-session-cache-memcached-tls
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS, "yes");
|
cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS, "yes");
|
||||||
break;
|
break;
|
||||||
|
case 109:
|
||||||
|
// --tls-session-cache-memcached-cert-file
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE,
|
||||||
|
optarg);
|
||||||
|
break;
|
||||||
|
case 110:
|
||||||
|
// --tls-session-cache-memcached-private-key-file
|
||||||
|
cmdcfgs.emplace_back(
|
||||||
|
SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE, optarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,6 +758,8 @@ enum {
|
||||||
SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD,
|
SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD,
|
||||||
SHRPX_OPTID_TLS_PROTO_LIST,
|
SHRPX_OPTID_TLS_PROTO_LIST,
|
||||||
SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED,
|
SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED,
|
||||||
|
SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE,
|
||||||
|
SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE,
|
||||||
SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS,
|
SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS,
|
||||||
SHRPX_OPTID_TLS_TICKET_KEY_CIPHER,
|
SHRPX_OPTID_TLS_TICKET_KEY_CIPHER,
|
||||||
SHRPX_OPTID_TLS_TICKET_KEY_FILE,
|
SHRPX_OPTID_TLS_TICKET_KEY_FILE,
|
||||||
|
@ -1406,6 +1408,11 @@ int option_lookup_token(const char *name, size_t namelen) {
|
||||||
break;
|
break;
|
||||||
case 37:
|
case 37:
|
||||||
switch (name[36]) {
|
switch (name[36]) {
|
||||||
|
case 'e':
|
||||||
|
if (util::strieq_l("tls-session-cache-memcached-cert-fil", name, 36)) {
|
||||||
|
return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
if (util::strieq_l("frontend-http2-connection-window-bit", name, 36)) {
|
if (util::strieq_l("frontend-http2-connection-window-bit", name, 36)) {
|
||||||
return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS;
|
return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS;
|
||||||
|
@ -1422,6 +1429,16 @@ int option_lookup_token(const char *name, size_t namelen) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 44:
|
||||||
|
switch (name[43]) {
|
||||||
|
case 'e':
|
||||||
|
if (util::strieq_l("tls-session-cache-memcached-private-key-fil", name,
|
||||||
|
43)) {
|
||||||
|
return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2242,6 +2259,14 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS:
|
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS:
|
||||||
mod_config()->tls.session_cache.memcached.tls = util::strieq(optarg, "yes");
|
mod_config()->tls.session_cache.memcached.tls = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE:
|
||||||
|
mod_config()->tls.session_cache.memcached.cert_file = optarg;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE:
|
||||||
|
mod_config()->tls.session_cache.memcached.private_key_file = optarg;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_CONF:
|
case SHRPX_OPTID_CONF:
|
||||||
LOG(WARN) << "conf: ignored";
|
LOG(WARN) << "conf: ignored";
|
||||||
|
|
|
@ -211,6 +211,10 @@ constexpr char SHRPX_OPT_BACKEND_TLS_SESSION_CACHE_PER_WORKER[] =
|
||||||
"backend-tls-session-cache-per-worker";
|
"backend-tls-session-cache-per-worker";
|
||||||
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS[] =
|
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS[] =
|
||||||
"tls-session-cache-memcached-tls";
|
"tls-session-cache-memcached-tls";
|
||||||
|
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE[] =
|
||||||
|
"tls-session-cache-memcached-cert-file";
|
||||||
|
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE[] =
|
||||||
|
"tls-session-cache-memcached-private-key-file";
|
||||||
|
|
||||||
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
|
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
|
||||||
|
|
||||||
|
@ -357,6 +361,9 @@ struct TLSConfig {
|
||||||
Address addr;
|
Address addr;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
std::unique_ptr<char[]> host;
|
std::unique_ptr<char[]> host;
|
||||||
|
// Client private key and certificate for authentication
|
||||||
|
ImmutableString private_key_file;
|
||||||
|
ImmutableString cert_file;
|
||||||
bool tls;
|
bool tls;
|
||||||
} memcached;
|
} memcached;
|
||||||
} session_cache;
|
} session_cache;
|
||||||
|
|
|
@ -193,15 +193,18 @@ int ConnectionHandler::create_single_worker() {
|
||||||
all_ssl_ctx_.push_back(cl_ssl_ctx);
|
all_ssl_ctx_.push_back(cl_ssl_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &session_cacheconf = get_config()->tls.session_cache;
|
auto &tlsconf = get_config()->tls;
|
||||||
|
auto &memcachedconf = get_config()->tls.session_cache.memcached;
|
||||||
|
|
||||||
SSL_CTX *session_cache_ssl_ctx = nullptr;
|
SSL_CTX *session_cache_ssl_ctx = nullptr;
|
||||||
if (session_cacheconf.memcached.tls) {
|
if (memcachedconf.tls) {
|
||||||
session_cache_ssl_ctx = ssl::create_ssl_client_context(
|
session_cache_ssl_ctx = ssl::create_ssl_client_context(
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
nb_.get(),
|
nb_.get(),
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
nullptr, nullptr, nullptr, StringRef(), nullptr);
|
StringRef::from_maybe_nullptr(tlsconf.cacert.get()),
|
||||||
|
StringRef(memcachedconf.cert_file),
|
||||||
|
StringRef(memcachedconf.private_key_file), StringRef(), nullptr);
|
||||||
all_ssl_ctx_.push_back(session_cache_ssl_ctx);
|
all_ssl_ctx_.push_back(session_cache_ssl_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,18 +241,21 @@ int ConnectionHandler::create_worker_thread(size_t num) {
|
||||||
all_ssl_ctx_.push_back(cl_ssl_ctx);
|
all_ssl_ctx_.push_back(cl_ssl_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &session_cacheconf = get_config()->tls.session_cache;
|
auto &tlsconf = get_config()->tls;
|
||||||
|
auto &memcachedconf = get_config()->tls.session_cache.memcached;
|
||||||
|
|
||||||
for (size_t i = 0; i < num; ++i) {
|
for (size_t i = 0; i < num; ++i) {
|
||||||
auto loop = ev_loop_new(0);
|
auto loop = ev_loop_new(0);
|
||||||
|
|
||||||
SSL_CTX *session_cache_ssl_ctx = nullptr;
|
SSL_CTX *session_cache_ssl_ctx = nullptr;
|
||||||
if (session_cacheconf.memcached.tls) {
|
if (memcachedconf.tls) {
|
||||||
session_cache_ssl_ctx = ssl::create_ssl_client_context(
|
session_cache_ssl_ctx = ssl::create_ssl_client_context(
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
nb_.get(),
|
nb_.get(),
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
nullptr, nullptr, nullptr, StringRef(), nullptr);
|
StringRef::from_maybe_nullptr(tlsconf.cacert.get()),
|
||||||
|
StringRef(memcachedconf.cert_file),
|
||||||
|
StringRef(memcachedconf.private_key_file), StringRef(), nullptr);
|
||||||
all_ssl_ctx_.push_back(session_cache_ssl_ctx);
|
all_ssl_ctx_.push_back(session_cache_ssl_ctx);
|
||||||
}
|
}
|
||||||
auto worker =
|
auto worker =
|
||||||
|
|
|
@ -662,8 +662,8 @@ SSL_CTX *create_ssl_client_context(
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
neverbleed_t *nb,
|
neverbleed_t *nb,
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
const char *cacert, const char *cert_file, const char *private_key_file,
|
const StringRef &cacert, const StringRef &cert_file,
|
||||||
const StringRef &alpn,
|
const StringRef &private_key_file, const StringRef &alpn,
|
||||||
int (*next_proto_select_cb)(SSL *s, unsigned char **out,
|
int (*next_proto_select_cb)(SSL *s, unsigned char **out,
|
||||||
unsigned char *outlen, const unsigned char *in,
|
unsigned char *outlen, const unsigned char *in,
|
||||||
unsigned int inlen, void *arg)) {
|
unsigned int inlen, void *arg)) {
|
||||||
|
@ -702,8 +702,8 @@ SSL_CTX *create_ssl_client_context(
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cacert) {
|
if (!cacert.empty()) {
|
||||||
if (SSL_CTX_load_verify_locations(ssl_ctx, cacert, nullptr) != 1) {
|
if (SSL_CTX_load_verify_locations(ssl_ctx, cacert.c_str(), nullptr) != 1) {
|
||||||
|
|
||||||
LOG(FATAL) << "Could not load trusted ca certificates from " << cacert
|
LOG(FATAL) << "Could not load trusted ca certificates from " << cacert
|
||||||
<< ": " << ERR_error_string(ERR_get_error(), nullptr);
|
<< ": " << ERR_error_string(ERR_get_error(), nullptr);
|
||||||
|
@ -711,8 +711,8 @@ SSL_CTX *create_ssl_client_context(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cert_file) {
|
if (!cert_file.empty()) {
|
||||||
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) {
|
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file.c_str()) != 1) {
|
||||||
|
|
||||||
LOG(FATAL) << "Could not load client certificate from " << cert_file
|
LOG(FATAL) << "Could not load client certificate from " << cert_file
|
||||||
<< ": " << ERR_error_string(ERR_get_error(), nullptr);
|
<< ": " << ERR_error_string(ERR_get_error(), nullptr);
|
||||||
|
@ -720,9 +720,9 @@ SSL_CTX *create_ssl_client_context(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (private_key_file) {
|
if (!private_key_file.empty()) {
|
||||||
#ifndef HAVE_NEVERBLEED
|
#ifndef HAVE_NEVERBLEED
|
||||||
if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file,
|
if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file.c_str(),
|
||||||
SSL_FILETYPE_PEM) != 1) {
|
SSL_FILETYPE_PEM) != 1) {
|
||||||
LOG(FATAL) << "Could not load client private key from "
|
LOG(FATAL) << "Could not load client private key from "
|
||||||
<< private_key_file << ": "
|
<< private_key_file << ": "
|
||||||
|
@ -731,7 +731,7 @@ SSL_CTX *create_ssl_client_context(
|
||||||
}
|
}
|
||||||
#else // HAVE_NEVERBLEED
|
#else // HAVE_NEVERBLEED
|
||||||
std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf;
|
std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf;
|
||||||
if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file,
|
if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file.c_str(),
|
||||||
errbuf.data()) != 1) {
|
errbuf.data()) != 1) {
|
||||||
LOG(FATAL) << "neverbleed_load_private_key_file: could not load client "
|
LOG(FATAL) << "neverbleed_load_private_key_file: could not load client "
|
||||||
"private key from " << private_key_file << ": "
|
"private key from " << private_key_file << ": "
|
||||||
|
@ -1323,8 +1323,10 @@ SSL_CTX *setup_downstream_client_ssl_context(
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
nb,
|
nb,
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
tlsconf.cacert.get(), tlsconf.client.cert_file.get(),
|
StringRef::from_maybe_nullptr(tlsconf.cacert.get()),
|
||||||
tlsconf.client.private_key_file.get(), alpn, next_proto_select_cb);
|
StringRef::from_maybe_nullptr(tlsconf.client.cert_file.get()),
|
||||||
|
StringRef::from_maybe_nullptr(tlsconf.client.private_key_file.get()),
|
||||||
|
alpn, next_proto_select_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
CertLookupTree *create_cert_lookup_tree() {
|
CertLookupTree *create_cert_lookup_tree() {
|
||||||
|
|
|
@ -75,8 +75,8 @@ SSL_CTX *create_ssl_client_context(
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
neverbleed_t *nb,
|
neverbleed_t *nb,
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
const char *cacert, const char *cert_file, const char *private_key_file,
|
const StringRef &cacert, const StringRef &cert_file,
|
||||||
const StringRef &alpn,
|
const StringRef &private_key_file, const StringRef &alpn,
|
||||||
int (*next_proto_select_cb)(SSL *s, unsigned char **out,
|
int (*next_proto_select_cb)(SSL *s, unsigned char **out,
|
||||||
unsigned char *outlen, const unsigned char *in,
|
unsigned char *outlen, const unsigned char *in,
|
||||||
unsigned int inlen, void *arg));
|
unsigned int inlen, void *arg));
|
||||||
|
|
|
@ -402,6 +402,13 @@ public:
|
||||||
static StringRef from_lit(const CharT(&s)[N]) {
|
static StringRef from_lit(const CharT(&s)[N]) {
|
||||||
return StringRef(s, N - 1);
|
return StringRef(s, N - 1);
|
||||||
}
|
}
|
||||||
|
static StringRef from_maybe_nullptr(const char *s) {
|
||||||
|
if (s == nullptr) {
|
||||||
|
return StringRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringRef(s);
|
||||||
|
}
|
||||||
|
|
||||||
const_iterator begin() const { return base; };
|
const_iterator begin() const { return base; };
|
||||||
const_iterator cbegin() const { return base; };
|
const_iterator cbegin() const { return base; };
|
||||||
|
|
Loading…
Reference in New Issue