nghttpx: Add encryption support for TLS ticket key retrieval

This commit is contained in:
Tatsuhiro Tsujikawa 2016-02-13 18:17:11 +09:00
parent 3297a303bf
commit 3a41e4dd1a
7 changed files with 115 additions and 13 deletions

View File

@ -117,7 +117,10 @@ OPTIONS = [
"backend-http1-tls",
"backend-tls-session-cache-per-worker",
"tls-session-cache-memcached-cert-file",
"tls-session-cache-memcached-private-key-file"
"tls-session-cache-memcached-private-key-file",
"tls-ticket-key-memcached-tls",
"tls-ticket-key-memcached-cert-file",
"tls-ticket-key-memcached-private-key-file"
]
LOGVARS = [

View File

@ -1520,16 +1520,16 @@ SSL/TLS:
ticket key sharing between nghttpx instances is not
required.
--tls-ticket-key-memcached=<HOST>,<PORT>
Specify address of memcached server to store session
cache. This enables shared TLS ticket key between
multiple nghttpx instances. nghttpx does not set TLS
ticket key to memcached. The external ticket key
generator is required. nghttpx just gets TLS ticket
keys from memcached, and use them, possibly replacing
current set of keys. It is up to extern TLS ticket key
generator to rotate keys frequently. See "TLS SESSION
TICKET RESUMPTION" section in manual page to know the
data format in memcached entry.
Specify address of memcached server to get TLS ticket
keys for session resumption. This enables shared TLS
ticket key between multiple nghttpx instances. nghttpx
does not set TLS ticket key to memcached. The external
ticket key generator is required. nghttpx just gets TLS
ticket keys from memcached, and use them, possibly
replacing current set of keys. It is up to extern TLS
ticket key generator to rotate keys frequently. See
"TLS SESSION TICKET RESUMPTION" section in manual page
to know the data format in memcached entry.
--tls-ticket-key-memcached-interval=<DURATION>
Set interval to get TLS ticket keys from memcached.
Default: )"
@ -1550,6 +1550,15 @@ SSL/TLS:
Specify cipher to encrypt TLS session ticket. Specify
either aes-128-cbc or aes-256-cbc. By default,
aes-128-cbc is used.
--tls-ticket-key-memcached-tls
Enable SSL/TLS on memcached connections to get TLS
ticket keys.
--tls-ticket-key-memcached-cert-file=<PATH>
Path to client certificate for memcached connections to
get TLS ticket keys.
--tls-ticket-key-memcached-private-key-file=<PATH>
Path to client private key for memcached connections to
get TLS ticket keys.
--fetch-ocsp-response-file=<PATH>
Path to fetch-ocsp-response script file. It should be
absolute path.
@ -2414,6 +2423,11 @@ int main(int argc, char **argv) {
&flag, 109},
{SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE,
required_argument, &flag, 110},
{SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS, no_argument, &flag, 111},
{SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE, required_argument, &flag,
112},
{SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE, required_argument,
&flag, 113},
{nullptr, 0, nullptr, 0}};
int option_index = 0;
@ -2886,6 +2900,20 @@ int main(int argc, char **argv) {
cmdcfgs.emplace_back(
SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE, optarg);
break;
case 111:
// --tls-ticket-key-memcached-tls
cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS, "yes");
break;
case 112:
// --tls-ticket-key-memcached-cert-file
cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE,
optarg);
break;
case 113:
// --tls-ticket-key-memcached-private-key-file
cmdcfgs.emplace_back(
SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE, optarg);
break;
default:
break;
}

View File

@ -764,9 +764,12 @@ enum {
SHRPX_OPTID_TLS_TICKET_KEY_CIPHER,
SHRPX_OPTID_TLS_TICKET_KEY_FILE,
SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED,
SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE,
SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL,
SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL,
SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY,
SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE,
SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS,
SHRPX_OPTID_USER,
SHRPX_OPTID_VERIFY_CLIENT,
SHRPX_OPTID_VERIFY_CLIENT_CACERT,
@ -1328,6 +1331,9 @@ int option_lookup_token(const char *name, size_t namelen) {
if (util::strieq_l("http2-max-concurrent-stream", name, 27)) {
return SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS;
}
if (util::strieq_l("tls-ticket-key-memcached-tl", name, 27)) {
return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS;
}
break;
}
break;
@ -1363,6 +1369,11 @@ int option_lookup_token(const char *name, size_t namelen) {
break;
case 34:
switch (name[33]) {
case 'e':
if (util::strieq_l("tls-ticket-key-memcached-cert-fil", name, 33)) {
return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE;
}
break;
case 'r':
if (util::strieq_l("frontend-http2-dump-request-heade", name, 33)) {
return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER;
@ -1429,6 +1440,16 @@ int option_lookup_token(const char *name, size_t namelen) {
break;
}
break;
case 41:
switch (name[40]) {
case 'e':
if (util::strieq_l("tls-ticket-key-memcached-private-key-fil", name,
40)) {
return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE;
}
break;
}
break;
case 44:
switch (name[43]) {
case 'e':
@ -2267,6 +2288,18 @@ int parse_config(const char *opt, const char *optarg,
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE:
mod_config()->tls.session_cache.memcached.private_key_file = optarg;
return 0;
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS:
mod_config()->tls.ticket.memcached.tls = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE:
mod_config()->tls.ticket.memcached.cert_file = optarg;
return 0;
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE:
mod_config()->tls.ticket.memcached.private_key_file = optarg;
return 0;
case SHRPX_OPTID_CONF:
LOG(WARN) << "conf: ignored";

View File

@ -215,6 +215,12 @@ 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 char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS[] =
"tls-ticket-key-memcached-tls";
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE[] =
"tls-ticket-key-memcached-cert-file";
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE[] =
"tls-ticket-key-memcached-private-key-file";
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
@ -341,6 +347,9 @@ struct TLSConfig {
Address addr;
uint16_t port;
std::unique_ptr<char[]> host;
// Client private key and certificate for authentication
ImmutableString private_key_file;
ImmutableString cert_file;
ev_tstamp interval;
// Maximum number of retries when getting TLS ticket key from
// mamcached, due to network error.
@ -348,6 +357,7 @@ struct TLSConfig {
// Maximum number of consecutive error from memcached, when this
// limit reached, TLS ticket is disabled.
size_t max_fail;
bool tls;
} memcached;
std::vector<std::string> files;
const EVP_CIPHER *cipher;

View File

@ -759,6 +759,23 @@ void ConnectionHandler::schedule_next_tls_ticket_key_memcached_get(
ev_timer_start(loop_, w);
}
SSL_CTX *ConnectionHandler::create_tls_ticket_key_memcached_ssl_ctx() {
auto &tlsconf = get_config()->tls;
auto &memcachedconf = get_config()->tls.ticket.memcached;
auto ssl_ctx = ssl::create_ssl_client_context(
#ifdef HAVE_NEVERBLEED
nb_.get(),
#endif // HAVE_NEVERBLEED
StringRef::from_maybe_nullptr(tlsconf.cacert.get()),
StringRef(memcachedconf.cert_file),
StringRef(memcachedconf.private_key_file), StringRef(), nullptr);
all_ssl_ctx_.push_back(ssl_ctx);
return ssl_ctx;
}
#ifdef HAVE_NEVERBLEED
void ConnectionHandler::set_neverbleed(std::unique_ptr<neverbleed_t> nb) {
nb_ = std::move(nb);

View File

@ -129,6 +129,7 @@ public:
on_tls_ticket_key_get_success(const std::shared_ptr<TicketKeys> &ticket_keys,
ev_timer *w);
void schedule_next_tls_ticket_key_memcached_get(ev_timer *w);
SSL_CTX *create_tls_ticket_key_memcached_ssl_ctx();
#ifdef HAVE_NEVERBLEED
void set_neverbleed(std::unique_ptr<neverbleed_t> nb);

View File

@ -420,14 +420,24 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
#endif // HAVE_NEVERBLEED
MemchunkPool mcpool;
ev_timer renew_ticket_key_timer;
if (!upstreamconf.no_tls) {
auto &ticketconf = get_config()->tls.ticket;
auto &memcachedconf = ticketconf.memcached;
if (ticketconf.memcached.host) {
SSL_CTX *ssl_ctx = nullptr;
if (memcachedconf.tls) {
ssl_ctx = conn_handler.create_tls_ticket_key_memcached_ssl_ctx();
}
conn_handler.set_tls_ticket_key_memcached_dispatcher(
make_unique<MemcachedDispatcher>(&ticketconf.memcached.addr, loop,
nullptr, "", nullptr));
make_unique<MemcachedDispatcher>(
&ticketconf.memcached.addr, loop, ssl_ctx,
StringRef(memcachedconf.host.get()), &mcpool));
ev_timer_init(&renew_ticket_key_timer, memcached_get_ticket_key_cb, 0.,
0.);