nghttpx: Structured TLS related configurations
This commit is contained in:
parent
b12af8c410
commit
f3e1dc7a4f
125
src/shrpx.cc
125
src/shrpx.cc
|
@ -903,9 +903,6 @@ void fill_default_config() {
|
||||||
mod_config()->server_name = "nghttpx nghttp2/" NGHTTP2_VERSION;
|
mod_config()->server_name = "nghttpx nghttp2/" NGHTTP2_VERSION;
|
||||||
mod_config()->host = strcopy("*");
|
mod_config()->host = strcopy("*");
|
||||||
mod_config()->port = 3000;
|
mod_config()->port = 3000;
|
||||||
mod_config()->private_key_file = nullptr;
|
|
||||||
mod_config()->private_key_passwd = nullptr;
|
|
||||||
mod_config()->cert_file = nullptr;
|
|
||||||
|
|
||||||
// Read timeout for HTTP2 upstream connection
|
// Read timeout for HTTP2 upstream connection
|
||||||
mod_config()->http2_upstream_read_timeout = 3_min;
|
mod_config()->http2_upstream_read_timeout = 3_min;
|
||||||
|
@ -957,14 +954,11 @@ void fill_default_config() {
|
||||||
mod_config()->syslog_facility = LOG_DAEMON;
|
mod_config()->syslog_facility = LOG_DAEMON;
|
||||||
// Default accept() backlog
|
// Default accept() backlog
|
||||||
mod_config()->backlog = 512;
|
mod_config()->backlog = 512;
|
||||||
mod_config()->ciphers = nullptr;
|
|
||||||
mod_config()->http2_proxy = false;
|
mod_config()->http2_proxy = false;
|
||||||
mod_config()->http2_bridge = false;
|
mod_config()->http2_bridge = false;
|
||||||
mod_config()->client_proxy = false;
|
mod_config()->client_proxy = false;
|
||||||
mod_config()->client = false;
|
mod_config()->client = false;
|
||||||
mod_config()->client_mode = false;
|
mod_config()->client_mode = false;
|
||||||
mod_config()->insecure = false;
|
|
||||||
mod_config()->cacert = nullptr;
|
|
||||||
mod_config()->pid_file = nullptr;
|
mod_config()->pid_file = nullptr;
|
||||||
mod_config()->user = nullptr;
|
mod_config()->user = nullptr;
|
||||||
mod_config()->uid = 0;
|
mod_config()->uid = 0;
|
||||||
|
@ -981,10 +975,6 @@ void fill_default_config() {
|
||||||
mod_config()->worker_read_burst = 0;
|
mod_config()->worker_read_burst = 0;
|
||||||
mod_config()->worker_write_rate = 0;
|
mod_config()->worker_write_rate = 0;
|
||||||
mod_config()->worker_write_burst = 0;
|
mod_config()->worker_write_burst = 0;
|
||||||
mod_config()->verify_client = false;
|
|
||||||
mod_config()->verify_client_cacert = nullptr;
|
|
||||||
mod_config()->client_private_key_file = nullptr;
|
|
||||||
mod_config()->client_cert_file = nullptr;
|
|
||||||
mod_config()->http2_upstream_dump_request_header = nullptr;
|
mod_config()->http2_upstream_dump_request_header = nullptr;
|
||||||
mod_config()->http2_upstream_dump_response_header = nullptr;
|
mod_config()->http2_upstream_dump_response_header = nullptr;
|
||||||
mod_config()->http2_no_cookie_crumbling = false;
|
mod_config()->http2_no_cookie_crumbling = false;
|
||||||
|
@ -1002,7 +992,6 @@ void fill_default_config() {
|
||||||
nghttp2_option_set_peer_max_concurrent_streams(
|
nghttp2_option_set_peer_max_concurrent_streams(
|
||||||
get_config()->http2_client_option, 100);
|
get_config()->http2_client_option, 100);
|
||||||
|
|
||||||
mod_config()->tls_proto_mask = 0;
|
|
||||||
mod_config()->no_location_rewrite = false;
|
mod_config()->no_location_rewrite = false;
|
||||||
mod_config()->no_host_rewrite = true;
|
mod_config()->no_host_rewrite = true;
|
||||||
mod_config()->argc = 0;
|
mod_config()->argc = 0;
|
||||||
|
@ -1015,23 +1004,42 @@ void fill_default_config() {
|
||||||
mod_config()->no_server_push = false;
|
mod_config()->no_server_push = false;
|
||||||
mod_config()->host_unix = false;
|
mod_config()->host_unix = false;
|
||||||
mod_config()->http2_downstream_connections_per_worker = 0;
|
mod_config()->http2_downstream_connections_per_worker = 0;
|
||||||
// ocsp update interval = 14400 secs = 4 hours, borrowed from h2o
|
|
||||||
mod_config()->ocsp_update_interval = 4_h;
|
|
||||||
mod_config()->fetch_ocsp_response_file =
|
|
||||||
strcopy(PKGDATADIR "/fetch-ocsp-response");
|
|
||||||
mod_config()->no_ocsp = false;
|
|
||||||
mod_config()->header_field_buffer = 64_k;
|
mod_config()->header_field_buffer = 64_k;
|
||||||
mod_config()->max_header_fields = 100;
|
mod_config()->max_header_fields = 100;
|
||||||
mod_config()->downstream_addr_group_catch_all = 0;
|
mod_config()->downstream_addr_group_catch_all = 0;
|
||||||
mod_config()->tls_ticket_key_cipher = EVP_aes_128_cbc();
|
|
||||||
mod_config()->tls_ticket_key_cipher_given = false;
|
|
||||||
mod_config()->tls_session_timeout = std::chrono::hours(12);
|
|
||||||
mod_config()->tls_ticket_key_memcached_max_retry = 3;
|
|
||||||
mod_config()->tls_ticket_key_memcached_max_fail = 2;
|
|
||||||
mod_config()->tls_ticket_key_memcached_interval = 10_min;
|
|
||||||
mod_config()->fastopen = 0;
|
mod_config()->fastopen = 0;
|
||||||
mod_config()->tls_dyn_rec_warmup_threshold = 1_m;
|
|
||||||
mod_config()->tls_dyn_rec_idle_timeout = 1.;
|
auto &tlsconf = mod_config()->tls;
|
||||||
|
{
|
||||||
|
auto &ticketconf = tlsconf.ticket;
|
||||||
|
ticketconf.cipher = EVP_aes_128_cbc();
|
||||||
|
ticketconf.cipher_given = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto &memcachedconf = ticketconf.memcached;
|
||||||
|
memcachedconf.max_retry = 3;
|
||||||
|
memcachedconf.max_fail = 2;
|
||||||
|
memcachedconf.interval = 10_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &ocspconf = tlsconf.ocsp;
|
||||||
|
// ocsp update interval = 14400 secs = 4 hours, borrowed from h2o
|
||||||
|
ocspconf.update_interval = 4_h;
|
||||||
|
ocspconf.fetch_ocsp_response_file =
|
||||||
|
strcopy(PKGDATADIR "/fetch-ocsp-response");
|
||||||
|
ocspconf.disabled = false;
|
||||||
|
|
||||||
|
auto &client_verify = tlsconf.client_verify;
|
||||||
|
client_verify.enabled = false;
|
||||||
|
|
||||||
|
auto &dyn_recconf = tlsconf.dyn_rec;
|
||||||
|
dyn_recconf.warmup_threshold = 1_m;
|
||||||
|
dyn_recconf.idle_timeout = 1.;
|
||||||
|
|
||||||
|
tlsconf.session_timeout = std::chrono::hours(12);
|
||||||
|
tlsconf.tls_proto_mask = 0;
|
||||||
|
tlsconf.insecure = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -1386,8 +1394,7 @@ SSL/TLS:
|
||||||
--tls-ticket-key-memcached-interval=<DURATION>
|
--tls-ticket-key-memcached-interval=<DURATION>
|
||||||
Set interval to get TLS ticket keys from memcached.
|
Set interval to get TLS ticket keys from memcached.
|
||||||
Default: )"
|
Default: )"
|
||||||
<< util::duration_str(get_config()->tls_ticket_key_memcached_interval)
|
<< util::duration_str(get_config()->tls.ticket.memcached.interval) << R"(
|
||||||
<< R"(
|
|
||||||
--tls-ticket-key-memcached-max-retry=<N>
|
--tls-ticket-key-memcached-max-retry=<N>
|
||||||
Set maximum number of consecutive retries before
|
Set maximum number of consecutive retries before
|
||||||
abandoning TLS ticket key retrieval. If this number is
|
abandoning TLS ticket key retrieval. If this number is
|
||||||
|
@ -1395,13 +1402,11 @@ SSL/TLS:
|
||||||
"failure" count is incremented by 1, which contributed
|
"failure" count is incremented by 1, which contributed
|
||||||
to the value controlled
|
to the value controlled
|
||||||
--tls-ticket-key-memcached-max-fail option.
|
--tls-ticket-key-memcached-max-fail option.
|
||||||
Default: )" << get_config()->tls_ticket_key_memcached_max_retry
|
Default: )" << get_config()->tls.ticket.memcached.max_retry << R"(
|
||||||
<< R"(
|
|
||||||
--tls-ticket-key-memcached-max-fail=<N>
|
--tls-ticket-key-memcached-max-fail=<N>
|
||||||
Set maximum number of consecutive failure before
|
Set maximum number of consecutive failure before
|
||||||
disabling TLS ticket until next scheduled key retrieval.
|
disabling TLS ticket until next scheduled key retrieval.
|
||||||
Default: )" << get_config()->tls_ticket_key_memcached_max_fail
|
Default: )" << get_config()->tls.ticket.memcached.max_fail << R"(
|
||||||
<< R"(
|
|
||||||
--tls-ticket-key-cipher=<CIPHER>
|
--tls-ticket-key-cipher=<CIPHER>
|
||||||
Specify cipher to encrypt TLS session ticket. Specify
|
Specify cipher to encrypt TLS session ticket. Specify
|
||||||
either aes-128-cbc or aes-256-cbc. By default,
|
either aes-128-cbc or aes-256-cbc. By default,
|
||||||
|
@ -1409,11 +1414,12 @@ SSL/TLS:
|
||||||
--fetch-ocsp-response-file=<PATH>
|
--fetch-ocsp-response-file=<PATH>
|
||||||
Path to fetch-ocsp-response script file. It should be
|
Path to fetch-ocsp-response script file. It should be
|
||||||
absolute path.
|
absolute path.
|
||||||
Default: )" << get_config()->fetch_ocsp_response_file.get() << R"(
|
Default: )"
|
||||||
|
<< get_config()->tls.ocsp.fetch_ocsp_response_file.get() << R"(
|
||||||
--ocsp-update-interval=<DURATION>
|
--ocsp-update-interval=<DURATION>
|
||||||
Set interval to update OCSP response cache.
|
Set interval to update OCSP response cache.
|
||||||
Default: )"
|
Default: )"
|
||||||
<< util::duration_str(get_config()->ocsp_update_interval) << R"(
|
<< util::duration_str(get_config()->tls.ocsp.update_interval) << R"(
|
||||||
--no-ocsp Disable OCSP stapling.
|
--no-ocsp Disable OCSP stapling.
|
||||||
--tls-session-cache-memcached=<HOST>,<PORT>
|
--tls-session-cache-memcached=<HOST>,<PORT>
|
||||||
Specify address of memcached server to store session
|
Specify address of memcached server to store session
|
||||||
|
@ -1431,14 +1437,14 @@ SSL/TLS:
|
||||||
period. This behaviour applies to all TLS based
|
period. This behaviour applies to all TLS based
|
||||||
frontends, and TLS HTTP/2 backends.
|
frontends, and TLS HTTP/2 backends.
|
||||||
Default: )"
|
Default: )"
|
||||||
<< util::utos_unit(get_config()->tls_dyn_rec_warmup_threshold) << R"(
|
<< util::utos_unit(get_config()->tls.dyn_rec.warmup_threshold) << R"(
|
||||||
--tls-dyn-rec-idle-timeout=<DURATION>
|
--tls-dyn-rec-idle-timeout=<DURATION>
|
||||||
Specify TLS dynamic record size behaviour timeout. See
|
Specify TLS dynamic record size behaviour timeout. See
|
||||||
--tls-dyn-rec-warmup-threshold for more information.
|
--tls-dyn-rec-warmup-threshold for more information.
|
||||||
This behaviour applies to all TLS based frontends, and
|
This behaviour applies to all TLS based frontends, and
|
||||||
TLS HTTP/2 backends.
|
TLS HTTP/2 backends.
|
||||||
Default: )"
|
Default: )"
|
||||||
<< util::duration_str(get_config()->tls_dyn_rec_idle_timeout) << R"(
|
<< util::duration_str(get_config()->tls.dyn_rec.idle_timeout) << R"(
|
||||||
|
|
||||||
HTTP/2 and SPDY:
|
HTTP/2 and SPDY:
|
||||||
-c, --http2-max-concurrent-streams=<N>
|
-c, --http2-max-concurrent-streams=<N>
|
||||||
|
@ -2410,18 +2416,19 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->npn_list.empty()) {
|
auto &tlsconf = mod_config()->tls;
|
||||||
mod_config()->npn_list = util::parse_config_str_list(DEFAULT_NPN_LIST);
|
|
||||||
|
if (tlsconf.npn_list.empty()) {
|
||||||
|
tlsconf.npn_list = util::parse_config_str_list(DEFAULT_NPN_LIST);
|
||||||
}
|
}
|
||||||
if (get_config()->tls_proto_list.empty()) {
|
if (tlsconf.tls_proto_list.empty()) {
|
||||||
mod_config()->tls_proto_list =
|
tlsconf.tls_proto_list =
|
||||||
util::parse_config_str_list(DEFAULT_TLS_PROTO_LIST);
|
util::parse_config_str_list(DEFAULT_TLS_PROTO_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->tls_proto_mask =
|
tlsconf.tls_proto_mask = ssl::create_tls_proto_mask(tlsconf.tls_proto_list);
|
||||||
ssl::create_tls_proto_mask(get_config()->tls_proto_list);
|
|
||||||
|
|
||||||
mod_config()->alpn_prefs = ssl::set_alpn_prefs(get_config()->npn_list);
|
tlsconf.alpn_prefs = ssl::set_alpn_prefs(tlsconf.npn_list);
|
||||||
|
|
||||||
if (get_config()->backend_ipv4 && get_config()->backend_ipv6) {
|
if (get_config()->backend_ipv4 && get_config()->backend_ipv6) {
|
||||||
LOG(FATAL) << "--backend-ipv4 and --backend-ipv6 cannot be used at the "
|
LOG(FATAL) << "--backend-ipv4 and --backend-ipv6 cannot be used at the "
|
||||||
|
@ -2454,18 +2461,18 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_config()->upstream_no_tls &&
|
if (!get_config()->upstream_no_tls &&
|
||||||
(!get_config()->private_key_file || !get_config()->cert_file)) {
|
(!tlsconf.private_key_file || !tlsconf.cert_file)) {
|
||||||
print_usage(std::cerr);
|
print_usage(std::cerr);
|
||||||
LOG(FATAL) << "Too few arguments";
|
LOG(FATAL) << "Too few arguments";
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_config()->upstream_no_tls && !get_config()->no_ocsp) {
|
if (!get_config()->upstream_no_tls && !tlsconf.ocsp.disabled) {
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
if (stat(get_config()->fetch_ocsp_response_file.get(), &buf) != 0) {
|
if (stat(tlsconf.ocsp.fetch_ocsp_response_file.get(), &buf) != 0) {
|
||||||
mod_config()->no_ocsp = true;
|
tlsconf.ocsp.disabled = true;
|
||||||
LOG(WARN) << "--fetch-ocsp-response-file: "
|
LOG(WARN) << "--fetch-ocsp-response-file: "
|
||||||
<< get_config()->fetch_ocsp_response_file.get()
|
<< tlsconf.ocsp.fetch_ocsp_response_file.get()
|
||||||
<< " not found. OCSP stapling has been disabled.";
|
<< " not found. OCSP stapling has been disabled.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2581,21 +2588,23 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->session_cache_memcached_host) {
|
{
|
||||||
if (resolve_hostname(&mod_config()->session_cache_memcached_addr,
|
auto &memcachedconf = tlsconf.session_cache.memcached;
|
||||||
get_config()->session_cache_memcached_host.get(),
|
if (memcachedconf.host) {
|
||||||
get_config()->session_cache_memcached_port,
|
if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.get(),
|
||||||
AF_UNSPEC) == -1) {
|
memcachedconf.port, AF_UNSPEC) == -1) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->tls_ticket_key_memcached_host) {
|
{
|
||||||
if (resolve_hostname(&mod_config()->tls_ticket_key_memcached_addr,
|
auto &memcachedconf = tlsconf.ticket.memcached;
|
||||||
get_config()->tls_ticket_key_memcached_host.get(),
|
if (memcachedconf.host) {
|
||||||
get_config()->tls_ticket_key_memcached_port,
|
if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.get(),
|
||||||
AF_UNSPEC) == -1) {
|
memcachedconf.port, AF_UNSPEC) == -1) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -375,8 +375,8 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
|
||||||
get_config()->upstream_read_timeout, get_config()->write_rate,
|
get_config()->upstream_read_timeout, get_config()->write_rate,
|
||||||
get_config()->write_burst, get_config()->read_rate,
|
get_config()->write_burst, get_config()->read_rate,
|
||||||
get_config()->read_burst, writecb, readcb, timeoutcb, this,
|
get_config()->read_burst, writecb, readcb, timeoutcb, this,
|
||||||
get_config()->tls_dyn_rec_warmup_threshold,
|
get_config()->tls.dyn_rec.warmup_threshold,
|
||||||
get_config()->tls_dyn_rec_idle_timeout),
|
get_config()->tls.dyn_rec.idle_timeout),
|
||||||
pinned_http2sessions_(
|
pinned_http2sessions_(
|
||||||
get_config()->downstream_proto == PROTO_HTTP2
|
get_config()->downstream_proto == PROTO_HTTP2
|
||||||
? make_unique<std::vector<ssize_t>>(
|
? make_unique<std::vector<ssize_t>>(
|
||||||
|
@ -521,7 +521,8 @@ int ClientHandler::validate_next_proto() {
|
||||||
CLOG(INFO, this) << "The negotiated next protocol: " << proto;
|
CLOG(INFO, this) << "The negotiated next protocol: " << proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ssl::in_proto_list(get_config()->npn_list, next_proto, next_proto_len)) {
|
if (!ssl::in_proto_list(get_config()->tls.npn_list, next_proto,
|
||||||
|
next_proto_len)) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
CLOG(INFO, this) << "The negotiated protocol is not supported";
|
CLOG(INFO, this) << "The negotiated protocol is not supported";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1601,7 +1601,7 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD:
|
case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD:
|
||||||
mod_config()->backend_tls_sni_name = optarg;
|
mod_config()->tls.backend_sni_name = optarg;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_PID_FILE:
|
case SHRPX_OPTID_PID_FILE:
|
||||||
|
@ -1622,7 +1622,7 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_PRIVATE_KEY_FILE:
|
case SHRPX_OPTID_PRIVATE_KEY_FILE:
|
||||||
mod_config()->private_key_file = strcopy(optarg);
|
mod_config()->tls.private_key_file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE: {
|
case SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE: {
|
||||||
|
@ -1631,16 +1631,16 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
LOG(ERROR) << opt << ": Couldn't read key file's passwd from " << optarg;
|
LOG(ERROR) << opt << ": Couldn't read key file's passwd from " << optarg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mod_config()->private_key_passwd = strcopy(passwd);
|
mod_config()->tls.private_key_passwd = strcopy(passwd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_CERTIFICATE_FILE:
|
case SHRPX_OPTID_CERTIFICATE_FILE:
|
||||||
mod_config()->cert_file = strcopy(optarg);
|
mod_config()->tls.cert_file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_DH_PARAM_FILE:
|
case SHRPX_OPTID_DH_PARAM_FILE:
|
||||||
mod_config()->dh_param_file = strcopy(optarg);
|
mod_config()->tls.dh_param_file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_SUBCERT: {
|
case SHRPX_OPTID_SUBCERT: {
|
||||||
|
@ -1649,7 +1649,7 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
if (sp) {
|
if (sp) {
|
||||||
std::string keyfile(optarg, sp);
|
std::string keyfile(optarg, sp);
|
||||||
// TODO Do we need private key for subcert?
|
// TODO Do we need private key for subcert?
|
||||||
mod_config()->subcerts.emplace_back(keyfile, sp + 1);
|
mod_config()->tls.subcerts.emplace_back(keyfile, sp + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1681,7 +1681,7 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_CIPHERS:
|
case SHRPX_OPTID_CIPHERS:
|
||||||
mod_config()->ciphers = strcopy(optarg);
|
mod_config()->tls.ciphers = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_CLIENT:
|
case SHRPX_OPTID_CLIENT:
|
||||||
|
@ -1689,11 +1689,11 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_INSECURE:
|
case SHRPX_OPTID_INSECURE:
|
||||||
mod_config()->insecure = util::strieq(optarg, "yes");
|
mod_config()->tls.insecure = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_CACERT:
|
case SHRPX_OPTID_CACERT:
|
||||||
mod_config()->cacert = strcopy(optarg);
|
mod_config()->tls.cacert = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_BACKEND_IPV4:
|
case SHRPX_OPTID_BACKEND_IPV4:
|
||||||
|
@ -1762,27 +1762,27 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
LOG(WARN) << opt << ": not implemented yet";
|
LOG(WARN) << opt << ": not implemented yet";
|
||||||
return parse_uint_with_unit(&mod_config()->worker_write_burst, opt, optarg);
|
return parse_uint_with_unit(&mod_config()->worker_write_burst, opt, optarg);
|
||||||
case SHRPX_OPTID_NPN_LIST:
|
case SHRPX_OPTID_NPN_LIST:
|
||||||
mod_config()->npn_list = util::parse_config_str_list(optarg);
|
mod_config()->tls.npn_list = util::parse_config_str_list(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_TLS_PROTO_LIST:
|
case SHRPX_OPTID_TLS_PROTO_LIST:
|
||||||
mod_config()->tls_proto_list = util::parse_config_str_list(optarg);
|
mod_config()->tls.tls_proto_list = util::parse_config_str_list(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_VERIFY_CLIENT:
|
case SHRPX_OPTID_VERIFY_CLIENT:
|
||||||
mod_config()->verify_client = util::strieq(optarg, "yes");
|
mod_config()->tls.client_verify.enabled = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_VERIFY_CLIENT_CACERT:
|
case SHRPX_OPTID_VERIFY_CLIENT_CACERT:
|
||||||
mod_config()->verify_client_cacert = strcopy(optarg);
|
mod_config()->tls.client_verify.cacert = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE:
|
case SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE:
|
||||||
mod_config()->client_private_key_file = strcopy(optarg);
|
mod_config()->tls.client.private_key_file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_CLIENT_CERT_FILE:
|
case SHRPX_OPTID_CLIENT_CERT_FILE:
|
||||||
mod_config()->client_cert_file = strcopy(optarg);
|
mod_config()->tls.client.cert_file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER:
|
case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER:
|
||||||
|
@ -1899,7 +1899,7 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
case SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT:
|
case SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT:
|
||||||
return parse_duration(&mod_config()->listener_disable_timeout, opt, optarg);
|
return parse_duration(&mod_config()->listener_disable_timeout, opt, optarg);
|
||||||
case SHRPX_OPTID_TLS_TICKET_KEY_FILE:
|
case SHRPX_OPTID_TLS_TICKET_KEY_FILE:
|
||||||
mod_config()->tls_ticket_key_files.push_back(optarg);
|
mod_config()->tls.ticket.files.push_back(optarg);
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_RLIMIT_NOFILE: {
|
case SHRPX_OPTID_RLIMIT_NOFILE: {
|
||||||
int n;
|
int n;
|
||||||
|
@ -1948,13 +1948,13 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return parse_uint(&mod_config()->http2_downstream_connections_per_worker,
|
return parse_uint(&mod_config()->http2_downstream_connections_per_worker,
|
||||||
opt, optarg);
|
opt, optarg);
|
||||||
case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE:
|
case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE:
|
||||||
mod_config()->fetch_ocsp_response_file = strcopy(optarg);
|
mod_config()->tls.ocsp.fetch_ocsp_response_file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_OCSP_UPDATE_INTERVAL:
|
case SHRPX_OPTID_OCSP_UPDATE_INTERVAL:
|
||||||
return parse_duration(&mod_config()->ocsp_update_interval, opt, optarg);
|
return parse_duration(&mod_config()->tls.ocsp.update_interval, opt, optarg);
|
||||||
case SHRPX_OPTID_NO_OCSP:
|
case SHRPX_OPTID_NO_OCSP:
|
||||||
mod_config()->no_ocsp = util::strieq(optarg, "yes");
|
mod_config()->tls.ocsp.disabled = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_HEADER_FIELD_BUFFER:
|
case SHRPX_OPTID_HEADER_FIELD_BUFFER:
|
||||||
|
@ -1980,15 +1980,15 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_TLS_TICKET_KEY_CIPHER:
|
case SHRPX_OPTID_TLS_TICKET_KEY_CIPHER:
|
||||||
if (util::strieq(optarg, "aes-128-cbc")) {
|
if (util::strieq(optarg, "aes-128-cbc")) {
|
||||||
mod_config()->tls_ticket_key_cipher = EVP_aes_128_cbc();
|
mod_config()->tls.ticket.cipher = EVP_aes_128_cbc();
|
||||||
} else if (util::strieq(optarg, "aes-256-cbc")) {
|
} else if (util::strieq(optarg, "aes-256-cbc")) {
|
||||||
mod_config()->tls_ticket_key_cipher = EVP_aes_256_cbc();
|
mod_config()->tls.ticket.cipher = EVP_aes_256_cbc();
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << opt
|
LOG(ERROR) << opt
|
||||||
<< ": unsupported cipher for ticket encryption: " << optarg;
|
<< ": unsupported cipher for ticket encryption: " << optarg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mod_config()->tls_ticket_key_cipher_given = true;
|
mod_config()->tls.ticket.cipher_given = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_HOST_REWRITE:
|
case SHRPX_OPTID_HOST_REWRITE:
|
||||||
|
@ -2001,8 +2001,9 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->session_cache_memcached_host = strcopy(host);
|
auto &memcachedconf = mod_config()->tls.session_cache.memcached;
|
||||||
mod_config()->session_cache_memcached_port = port;
|
memcachedconf.host = strcopy(host);
|
||||||
|
memcachedconf.port = port;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2012,13 +2013,14 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->tls_ticket_key_memcached_host = strcopy(host);
|
auto &memcachedconf = mod_config()->tls.ticket.memcached;
|
||||||
mod_config()->tls_ticket_key_memcached_port = port;
|
memcachedconf.host = strcopy(host);
|
||||||
|
memcachedconf.port = port;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL:
|
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL:
|
||||||
return parse_duration(&mod_config()->tls_ticket_key_memcached_interval, opt,
|
return parse_duration(&mod_config()->tls.ticket.memcached.interval, opt,
|
||||||
optarg);
|
optarg);
|
||||||
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY: {
|
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY: {
|
||||||
int n;
|
int n;
|
||||||
|
@ -2031,11 +2033,11 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->tls_ticket_key_memcached_max_retry = n;
|
mod_config()->tls.ticket.memcached.max_retry = n;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL:
|
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL:
|
||||||
return parse_uint(&mod_config()->tls_ticket_key_memcached_max_fail, opt,
|
return parse_uint(&mod_config()->tls.ticket.memcached.max_fail, opt,
|
||||||
optarg);
|
optarg);
|
||||||
case SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD: {
|
case SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD: {
|
||||||
size_t n;
|
size_t n;
|
||||||
|
@ -2043,13 +2045,13 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->tls_dyn_rec_warmup_threshold = n;
|
mod_config()->tls.dyn_rec.warmup_threshold = n;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT:
|
case SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT:
|
||||||
return parse_duration(&mod_config()->tls_dyn_rec_idle_timeout, opt, optarg);
|
return parse_duration(&mod_config()->tls.dyn_rec.idle_timeout, opt, optarg);
|
||||||
|
|
||||||
case SHRPX_OPTID_MRUBY_FILE:
|
case SHRPX_OPTID_MRUBY_FILE:
|
||||||
#ifdef HAVE_MRUBY
|
#ifdef HAVE_MRUBY
|
||||||
|
|
|
@ -292,25 +292,94 @@ struct HttpProxy {
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Config {
|
struct TLSConfig {
|
||||||
|
// RFC 5077 Session ticket related configurations
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
Address addr;
|
||||||
|
uint16_t port;
|
||||||
|
std::unique_ptr<char[]> host;
|
||||||
|
ev_tstamp interval;
|
||||||
|
// Maximum number of retries when getting TLS ticket key from
|
||||||
|
// mamcached, due to network error.
|
||||||
|
size_t max_retry;
|
||||||
|
// Maximum number of consecutive error from memcached, when this
|
||||||
|
// limit reached, TLS ticket is disabled.
|
||||||
|
size_t max_fail;
|
||||||
|
} memcached;
|
||||||
|
std::vector<std::string> files;
|
||||||
|
const EVP_CIPHER *cipher;
|
||||||
|
// true if --tls-ticket-key-cipher is used
|
||||||
|
bool cipher_given;
|
||||||
|
} ticket;
|
||||||
|
|
||||||
|
// Session cache related configurations
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
Address addr;
|
||||||
|
uint16_t port;
|
||||||
|
std::unique_ptr<char[]> host;
|
||||||
|
} memcached;
|
||||||
|
} session_cache;
|
||||||
|
|
||||||
|
// Dynamic record sizing configurations
|
||||||
|
struct {
|
||||||
|
size_t warmup_threshold;
|
||||||
|
ev_tstamp idle_timeout;
|
||||||
|
} dyn_rec;
|
||||||
|
|
||||||
|
// OCSP realted configurations
|
||||||
|
struct {
|
||||||
|
ev_tstamp update_interval;
|
||||||
|
std::unique_ptr<char[]> fetch_ocsp_response_file;
|
||||||
|
bool disabled;
|
||||||
|
} ocsp;
|
||||||
|
|
||||||
|
// Client verification configurations
|
||||||
|
struct {
|
||||||
|
// Path to file containing CA certificate solely used for client
|
||||||
|
// certificate validation
|
||||||
|
std::unique_ptr<char[]> cacert;
|
||||||
|
bool enabled;
|
||||||
|
} client_verify;
|
||||||
|
|
||||||
|
// Client private key and certificate used in backend connections.
|
||||||
|
struct {
|
||||||
|
std::unique_ptr<char[]> private_key_file;
|
||||||
|
std::unique_ptr<char[]> cert_file;
|
||||||
|
} client;
|
||||||
|
|
||||||
// The list of (private key file, certificate file) pair
|
// The list of (private key file, certificate file) pair
|
||||||
std::vector<std::pair<std::string, std::string>> subcerts;
|
std::vector<std::pair<std::string, std::string>> subcerts;
|
||||||
std::vector<AltSvc> altsvcs;
|
|
||||||
std::vector<std::pair<std::string, std::string>> add_request_headers;
|
|
||||||
std::vector<std::pair<std::string, std::string>> add_response_headers;
|
|
||||||
std::vector<unsigned char> alpn_prefs;
|
std::vector<unsigned char> alpn_prefs;
|
||||||
std::vector<LogFragment> accesslog_format;
|
|
||||||
std::vector<DownstreamAddrGroup> downstream_addr_groups;
|
|
||||||
std::vector<std::string> tls_ticket_key_files;
|
|
||||||
// list of supported NPN/ALPN protocol strings in the order of
|
// list of supported NPN/ALPN protocol strings in the order of
|
||||||
// preference.
|
// preference.
|
||||||
std::vector<std::string> npn_list;
|
std::vector<std::string> npn_list;
|
||||||
// list of supported SSL/TLS protocol strings.
|
// list of supported SSL/TLS protocol strings.
|
||||||
std::vector<std::string> tls_proto_list;
|
std::vector<std::string> tls_proto_list;
|
||||||
Address session_cache_memcached_addr;
|
// Bit mask to disable SSL/TLS protocol versions. This will be
|
||||||
Address tls_ticket_key_memcached_addr;
|
// passed to SSL_CTX_set_options().
|
||||||
|
long int tls_proto_mask;
|
||||||
|
std::string backend_sni_name;
|
||||||
|
std::chrono::seconds session_timeout;
|
||||||
|
std::unique_ptr<char[]> private_key_file;
|
||||||
|
std::unique_ptr<char[]> private_key_passwd;
|
||||||
|
std::unique_ptr<char[]> cert_file;
|
||||||
|
std::unique_ptr<char[]> dh_param_file;
|
||||||
|
std::unique_ptr<char[]> ciphers;
|
||||||
|
std::unique_ptr<char[]> cacert;
|
||||||
|
bool insecure;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Config {
|
||||||
|
std::vector<AltSvc> altsvcs;
|
||||||
|
std::vector<std::pair<std::string, std::string>> add_request_headers;
|
||||||
|
std::vector<std::pair<std::string, std::string>> add_response_headers;
|
||||||
|
std::vector<LogFragment> accesslog_format;
|
||||||
|
std::vector<DownstreamAddrGroup> downstream_addr_groups;
|
||||||
Router router;
|
Router router;
|
||||||
HttpProxy downstream_http_proxy;
|
HttpProxy downstream_http_proxy;
|
||||||
|
TLSConfig tls;
|
||||||
// obfuscated value used in "by" parameter of Forwarded header
|
// obfuscated value used in "by" parameter of Forwarded header
|
||||||
// field.
|
// field.
|
||||||
std::string forwarded_by_obfuscated;
|
std::string forwarded_by_obfuscated;
|
||||||
|
@ -318,9 +387,7 @@ struct Config {
|
||||||
// field. This is only used when user defined static obfuscated
|
// field. This is only used when user defined static obfuscated
|
||||||
// string is provided.
|
// string is provided.
|
||||||
std::string forwarded_for_obfuscated;
|
std::string forwarded_for_obfuscated;
|
||||||
std::string backend_tls_sni_name;
|
|
||||||
StringRef server_name;
|
StringRef server_name;
|
||||||
std::chrono::seconds tls_session_timeout;
|
|
||||||
ev_tstamp http2_upstream_read_timeout;
|
ev_tstamp http2_upstream_read_timeout;
|
||||||
ev_tstamp upstream_read_timeout;
|
ev_tstamp upstream_read_timeout;
|
||||||
ev_tstamp upstream_write_timeout;
|
ev_tstamp upstream_write_timeout;
|
||||||
|
@ -330,32 +397,16 @@ struct Config {
|
||||||
ev_tstamp stream_write_timeout;
|
ev_tstamp stream_write_timeout;
|
||||||
ev_tstamp downstream_idle_read_timeout;
|
ev_tstamp downstream_idle_read_timeout;
|
||||||
ev_tstamp listener_disable_timeout;
|
ev_tstamp listener_disable_timeout;
|
||||||
ev_tstamp ocsp_update_interval;
|
|
||||||
ev_tstamp tls_ticket_key_memcached_interval;
|
|
||||||
// address of frontend connection. This could be a path to UNIX
|
// address of frontend connection. This could be a path to UNIX
|
||||||
// domain socket. In this case, |host_unix| must be true.
|
// domain socket. In this case, |host_unix| must be true.
|
||||||
std::unique_ptr<char[]> host;
|
std::unique_ptr<char[]> host;
|
||||||
std::unique_ptr<char[]> private_key_file;
|
|
||||||
std::unique_ptr<char[]> private_key_passwd;
|
|
||||||
std::unique_ptr<char[]> cert_file;
|
|
||||||
std::unique_ptr<char[]> dh_param_file;
|
|
||||||
std::unique_ptr<char[]> pid_file;
|
std::unique_ptr<char[]> pid_file;
|
||||||
std::unique_ptr<char[]> conf_path;
|
std::unique_ptr<char[]> conf_path;
|
||||||
std::unique_ptr<char[]> ciphers;
|
|
||||||
std::unique_ptr<char[]> cacert;
|
|
||||||
std::unique_ptr<char[]> http2_upstream_dump_request_header_file;
|
std::unique_ptr<char[]> http2_upstream_dump_request_header_file;
|
||||||
std::unique_ptr<char[]> http2_upstream_dump_response_header_file;
|
std::unique_ptr<char[]> http2_upstream_dump_response_header_file;
|
||||||
// Path to file containing CA certificate solely used for client
|
|
||||||
// certificate validation
|
|
||||||
std::unique_ptr<char[]> verify_client_cacert;
|
|
||||||
std::unique_ptr<char[]> client_private_key_file;
|
|
||||||
std::unique_ptr<char[]> client_cert_file;
|
|
||||||
std::unique_ptr<char[]> accesslog_file;
|
std::unique_ptr<char[]> accesslog_file;
|
||||||
std::unique_ptr<char[]> errorlog_file;
|
std::unique_ptr<char[]> errorlog_file;
|
||||||
std::unique_ptr<char[]> fetch_ocsp_response_file;
|
|
||||||
std::unique_ptr<char[]> user;
|
std::unique_ptr<char[]> user;
|
||||||
std::unique_ptr<char[]> session_cache_memcached_host;
|
|
||||||
std::unique_ptr<char[]> tls_ticket_key_memcached_host;
|
|
||||||
std::unique_ptr<char[]> mruby_file;
|
std::unique_ptr<char[]> mruby_file;
|
||||||
FILE *http2_upstream_dump_request_header;
|
FILE *http2_upstream_dump_request_header;
|
||||||
FILE *http2_upstream_dump_response_header;
|
FILE *http2_upstream_dump_response_header;
|
||||||
|
@ -363,7 +414,6 @@ struct Config {
|
||||||
nghttp2_session_callbacks *http2_downstream_callbacks;
|
nghttp2_session_callbacks *http2_downstream_callbacks;
|
||||||
nghttp2_option *http2_option;
|
nghttp2_option *http2_option;
|
||||||
nghttp2_option *http2_client_option;
|
nghttp2_option *http2_client_option;
|
||||||
const EVP_CIPHER *tls_ticket_key_cipher;
|
|
||||||
char **original_argv;
|
char **original_argv;
|
||||||
char **argv;
|
char **argv;
|
||||||
char *cwd;
|
char *cwd;
|
||||||
|
@ -393,15 +443,6 @@ struct Config {
|
||||||
size_t max_header_fields;
|
size_t max_header_fields;
|
||||||
// The index of catch-all group in downstream_addr_groups.
|
// The index of catch-all group in downstream_addr_groups.
|
||||||
size_t downstream_addr_group_catch_all;
|
size_t downstream_addr_group_catch_all;
|
||||||
// Maximum number of retries when getting TLS ticket key from
|
|
||||||
// mamcached, due to network error.
|
|
||||||
size_t tls_ticket_key_memcached_max_retry;
|
|
||||||
// Maximum number of consecutive error from memcached, when this
|
|
||||||
// limit reached, TLS ticket is disabled.
|
|
||||||
size_t tls_ticket_key_memcached_max_fail;
|
|
||||||
// Bit mask to disable SSL/TLS protocol versions. This will be
|
|
||||||
// passed to SSL_CTX_set_options().
|
|
||||||
long int tls_proto_mask;
|
|
||||||
// downstream protocol; this will be determined by given options.
|
// downstream protocol; this will be determined by given options.
|
||||||
shrpx_proto downstream_proto;
|
shrpx_proto downstream_proto;
|
||||||
// bitwise-OR of one or more of shrpx_forwarded_param values.
|
// bitwise-OR of one or more of shrpx_forwarded_param values.
|
||||||
|
@ -424,11 +465,8 @@ struct Config {
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
// port in http proxy URI
|
// port in http proxy URI
|
||||||
uint16_t downstream_http_proxy_port;
|
uint16_t downstream_http_proxy_port;
|
||||||
uint16_t session_cache_memcached_port;
|
|
||||||
uint16_t tls_ticket_key_memcached_port;
|
|
||||||
bool verbose;
|
bool verbose;
|
||||||
bool daemon;
|
bool daemon;
|
||||||
bool verify_client;
|
|
||||||
bool http2_proxy;
|
bool http2_proxy;
|
||||||
bool http2_bridge;
|
bool http2_bridge;
|
||||||
bool client_proxy;
|
bool client_proxy;
|
||||||
|
@ -445,7 +483,6 @@ struct Config {
|
||||||
bool client;
|
bool client;
|
||||||
// true if --client or --client-proxy are enabled.
|
// true if --client or --client-proxy are enabled.
|
||||||
bool client_mode;
|
bool client_mode;
|
||||||
bool insecure;
|
|
||||||
bool backend_ipv4;
|
bool backend_ipv4;
|
||||||
bool backend_ipv6;
|
bool backend_ipv6;
|
||||||
bool http2_no_cookie_crumbling;
|
bool http2_no_cookie_crumbling;
|
||||||
|
@ -455,12 +492,7 @@ struct Config {
|
||||||
bool no_server_push;
|
bool no_server_push;
|
||||||
// true if host contains UNIX domain socket path
|
// true if host contains UNIX domain socket path
|
||||||
bool host_unix;
|
bool host_unix;
|
||||||
bool no_ocsp;
|
|
||||||
// true if --tls-ticket-key-cipher is used
|
|
||||||
bool tls_ticket_key_cipher_given;
|
|
||||||
bool accept_proxy_protocol;
|
bool accept_proxy_protocol;
|
||||||
size_t tls_dyn_rec_warmup_threshold;
|
|
||||||
ev_tstamp tls_dyn_rec_idle_timeout;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Config *get_config();
|
const Config *get_config();
|
||||||
|
|
|
@ -450,7 +450,7 @@ int ConnectionHandler::start_ocsp_update(const char *cert_file) {
|
||||||
assert(!ev_is_active(&ocsp_.chldev));
|
assert(!ev_is_active(&ocsp_.chldev));
|
||||||
|
|
||||||
char *const argv[] = {
|
char *const argv[] = {
|
||||||
const_cast<char *>(get_config()->fetch_ocsp_response_file.get()),
|
const_cast<char *>(get_config()->tls.ocsp.fetch_ocsp_response_file.get()),
|
||||||
const_cast<char *>(cert_file), nullptr};
|
const_cast<char *>(cert_file), nullptr};
|
||||||
char *const envp[] = {nullptr};
|
char *const envp[] = {nullptr};
|
||||||
|
|
||||||
|
@ -634,7 +634,7 @@ void ConnectionHandler::proceed_next_cert_ocsp() {
|
||||||
if (ocsp_.next == all_ssl_ctx_.size()) {
|
if (ocsp_.next == all_ssl_ctx_.size()) {
|
||||||
ocsp_.next = 0;
|
ocsp_.next = 0;
|
||||||
// We have updated all ocsp response, and schedule next update.
|
// We have updated all ocsp response, and schedule next update.
|
||||||
ev_timer_set(&ocsp_timer_, get_config()->ocsp_update_interval, 0.);
|
ev_timer_set(&ocsp_timer_, get_config()->tls.ocsp.update_interval, 0.);
|
||||||
ev_timer_start(loop_, &ocsp_timer_);
|
ev_timer_start(loop_, &ocsp_timer_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -673,7 +673,7 @@ ConnectionHandler::get_tls_ticket_key_memcached_dispatcher() const {
|
||||||
|
|
||||||
void ConnectionHandler::on_tls_ticket_key_network_error(ev_timer *w) {
|
void ConnectionHandler::on_tls_ticket_key_network_error(ev_timer *w) {
|
||||||
if (++tls_ticket_key_memcached_get_retry_count_ >=
|
if (++tls_ticket_key_memcached_get_retry_count_ >=
|
||||||
get_config()->tls_ticket_key_memcached_max_retry) {
|
get_config()->tls.ticket.memcached.max_retry) {
|
||||||
LOG(WARN) << "Memcached: tls ticket get retry all failed "
|
LOG(WARN) << "Memcached: tls ticket get retry all failed "
|
||||||
<< tls_ticket_key_memcached_get_retry_count_ << " times.";
|
<< tls_ticket_key_memcached_get_retry_count_ << " times.";
|
||||||
|
|
||||||
|
@ -697,7 +697,7 @@ void ConnectionHandler::on_tls_ticket_key_not_found(ev_timer *w) {
|
||||||
tls_ticket_key_memcached_get_retry_count_ = 0;
|
tls_ticket_key_memcached_get_retry_count_ = 0;
|
||||||
|
|
||||||
if (++tls_ticket_key_memcached_fail_count_ >=
|
if (++tls_ticket_key_memcached_fail_count_ >=
|
||||||
get_config()->tls_ticket_key_memcached_max_fail) {
|
get_config()->tls.ticket.memcached.max_fail) {
|
||||||
LOG(WARN) << "Memcached: could not get tls ticket; disable tls ticket";
|
LOG(WARN) << "Memcached: could not get tls ticket; disable tls ticket";
|
||||||
|
|
||||||
tls_ticket_key_memcached_fail_count_ = 0;
|
tls_ticket_key_memcached_fail_count_ = 0;
|
||||||
|
@ -742,7 +742,7 @@ void ConnectionHandler::on_tls_ticket_key_get_success(
|
||||||
|
|
||||||
void ConnectionHandler::schedule_next_tls_ticket_key_memcached_get(
|
void ConnectionHandler::schedule_next_tls_ticket_key_memcached_get(
|
||||||
ev_timer *w) {
|
ev_timer *w) {
|
||||||
ev_timer_set(w, get_config()->tls_ticket_key_memcached_interval, 0.);
|
ev_timer_set(w, get_config()->tls.ticket.memcached.interval, 0.);
|
||||||
ev_timer_start(loop_, w);
|
ev_timer_start(loop_, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,8 +148,8 @@ Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx,
|
||||||
: conn_(loop, -1, nullptr, worker->get_mcpool(),
|
: conn_(loop, -1, nullptr, worker->get_mcpool(),
|
||||||
get_config()->downstream_write_timeout,
|
get_config()->downstream_write_timeout,
|
||||||
get_config()->downstream_read_timeout, 0, 0, 0, 0, writecb, readcb,
|
get_config()->downstream_read_timeout, 0, 0, 0, 0, writecb, readcb,
|
||||||
timeoutcb, this, get_config()->tls_dyn_rec_warmup_threshold,
|
timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold,
|
||||||
get_config()->tls_dyn_rec_idle_timeout),
|
get_config()->tls.dyn_rec.idle_timeout),
|
||||||
worker_(worker), connect_blocker_(connect_blocker), ssl_ctx_(ssl_ctx),
|
worker_(worker), connect_blocker_(connect_blocker), ssl_ctx_(ssl_ctx),
|
||||||
session_(nullptr), data_pending_(nullptr), data_pendinglen_(0),
|
session_(nullptr), data_pending_(nullptr), data_pendinglen_(0),
|
||||||
addr_idx_(0), group_(group), index_(idx), state_(DISCONNECTED),
|
addr_idx_(0), group_(group), index_(idx), state_(DISCONNECTED),
|
||||||
|
@ -331,8 +331,8 @@ int Http2Session::initiate_connection() {
|
||||||
conn_.set_ssl(ssl);
|
conn_.set_ssl(ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef sni_name = !get_config()->backend_tls_sni_name.empty()
|
StringRef sni_name = !get_config()->tls.backend_sni_name.empty()
|
||||||
? get_config()->backend_tls_sni_name
|
? get_config()->tls.backend_sni_name
|
||||||
: downstream_addr.host;
|
: downstream_addr.host;
|
||||||
|
|
||||||
if (!util::numeric_host(sni_name.c_str())) {
|
if (!util::numeric_host(sni_name.c_str())) {
|
||||||
|
@ -1718,7 +1718,7 @@ int Http2Session::tls_handshake() {
|
||||||
SSLOG(INFO, this) << "SSL/TLS handshake completed";
|
SSLOG(INFO, this) << "SSL/TLS handshake completed";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_config()->downstream_no_tls && !get_config()->insecure &&
|
if (!get_config()->downstream_no_tls && !get_config()->tls.insecure &&
|
||||||
check_cert() != 0) {
|
check_cert() != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,8 +115,8 @@ HttpDownstreamConnection::HttpDownstreamConnection(
|
||||||
: DownstreamConnection(dconn_pool),
|
: DownstreamConnection(dconn_pool),
|
||||||
conn_(loop, -1, nullptr, nullptr, get_config()->downstream_write_timeout,
|
conn_(loop, -1, nullptr, nullptr, get_config()->downstream_write_timeout,
|
||||||
get_config()->downstream_read_timeout, 0, 0, 0, 0, connectcb,
|
get_config()->downstream_read_timeout, 0, 0, 0, 0, connectcb,
|
||||||
readcb, timeoutcb, this, get_config()->tls_dyn_rec_warmup_threshold,
|
readcb, timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold,
|
||||||
get_config()->tls_dyn_rec_idle_timeout),
|
get_config()->tls.dyn_rec.idle_timeout),
|
||||||
ioctrl_(&conn_.rlimit), response_htp_{0}, group_(group), addr_idx_(0),
|
ioctrl_(&conn_.rlimit), response_htp_{0}, group_(group), addr_idx_(0),
|
||||||
connected_(false) {}
|
connected_(false) {}
|
||||||
|
|
||||||
|
|
100
src/shrpx_ssl.cc
100
src/shrpx_ssl.cc
|
@ -70,7 +70,7 @@ namespace ssl {
|
||||||
namespace {
|
namespace {
|
||||||
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
|
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
|
||||||
void *arg) {
|
void *arg) {
|
||||||
auto &prefs = get_config()->alpn_prefs;
|
auto &prefs = get_config()->tls.alpn_prefs;
|
||||||
*data = prefs.data();
|
*data = prefs.data();
|
||||||
*len = prefs.size();
|
*len = prefs.size();
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
@ -124,13 +124,13 @@ set_alpn_prefs(const std::vector<std::string> &protos) {
|
||||||
namespace {
|
namespace {
|
||||||
int ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data) {
|
int ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data) {
|
||||||
auto config = static_cast<Config *>(user_data);
|
auto config = static_cast<Config *>(user_data);
|
||||||
int len = (int)strlen(config->private_key_passwd.get());
|
int len = (int)strlen(config->tls.private_key_passwd.get());
|
||||||
if (size < len + 1) {
|
if (size < len + 1) {
|
||||||
LOG(ERROR) << "ssl_pem_passwd_cb: buf is too small " << size;
|
LOG(ERROR) << "ssl_pem_passwd_cb: buf is too small " << size;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Copy string including last '\0'.
|
// Copy string including last '\0'.
|
||||||
memcpy(buf, config->private_key_passwd.get(), len + 1);
|
memcpy(buf, config->tls.private_key_passwd.get(), len + 1);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -346,7 +346,7 @@ int ticket_key_cb(SSL *ssl, unsigned char *key_name, unsigned char *iv,
|
||||||
|
|
||||||
std::copy(std::begin(key.data.name), std::end(key.data.name), key_name);
|
std::copy(std::begin(key.data.name), std::end(key.data.name), key_name);
|
||||||
|
|
||||||
EVP_EncryptInit_ex(ctx, get_config()->tls_ticket_key_cipher, nullptr,
|
EVP_EncryptInit_ex(ctx, get_config()->tls.ticket.cipher, nullptr,
|
||||||
key.data.enc_key.data(), iv);
|
key.data.enc_key.data(), iv);
|
||||||
HMAC_Init_ex(hctx, key.data.hmac_key.data(), key.hmac_keylen, key.hmac,
|
HMAC_Init_ex(hctx, key.data.hmac_key.data(), key.hmac_keylen, key.hmac,
|
||||||
nullptr);
|
nullptr);
|
||||||
|
@ -411,7 +411,7 @@ int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||||
// We assume that get_config()->npn_list contains ALPN protocol
|
// We assume that get_config()->npn_list contains ALPN protocol
|
||||||
// identifier sorted by preference order. So we just break when we
|
// identifier sorted by preference order. So we just break when we
|
||||||
// found the first overlap.
|
// found the first overlap.
|
||||||
for (const auto &target_proto_id : get_config()->npn_list) {
|
for (const auto &target_proto_id : get_config()->tls.npn_list) {
|
||||||
for (auto p = in, end = in + inlen; p < end;) {
|
for (auto p = in, end = in + inlen; p < end;) {
|
||||||
auto proto_id = p + 1;
|
auto proto_id = p + 1;
|
||||||
auto proto_len = *p;
|
auto proto_len = *p;
|
||||||
|
@ -477,22 +477,24 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_SINGLE_ECDH_USE |
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_SINGLE_ECDH_USE |
|
||||||
SSL_OP_SINGLE_DH_USE | SSL_OP_CIPHER_SERVER_PREFERENCE;
|
SSL_OP_SINGLE_DH_USE | SSL_OP_CIPHER_SERVER_PREFERENCE;
|
||||||
|
|
||||||
SSL_CTX_set_options(ssl_ctx, ssl_opts | get_config()->tls_proto_mask);
|
auto &tlsconf = get_config()->tls;
|
||||||
|
|
||||||
|
SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask);
|
||||||
|
|
||||||
const unsigned char sid_ctx[] = "shrpx";
|
const unsigned char sid_ctx[] = "shrpx";
|
||||||
SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1);
|
SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1);
|
||||||
SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_SERVER);
|
SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_SERVER);
|
||||||
|
|
||||||
if (get_config()->session_cache_memcached_host) {
|
if (tlsconf.session_cache.memcached.host) {
|
||||||
SSL_CTX_sess_set_new_cb(ssl_ctx, tls_session_new_cb);
|
SSL_CTX_sess_set_new_cb(ssl_ctx, tls_session_new_cb);
|
||||||
SSL_CTX_sess_set_get_cb(ssl_ctx, tls_session_get_cb);
|
SSL_CTX_sess_set_get_cb(ssl_ctx, tls_session_get_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_CTX_set_timeout(ssl_ctx, get_config()->tls_session_timeout.count());
|
SSL_CTX_set_timeout(ssl_ctx, tlsconf.session_timeout.count());
|
||||||
|
|
||||||
const char *ciphers;
|
const char *ciphers;
|
||||||
if (get_config()->ciphers) {
|
if (tlsconf.ciphers) {
|
||||||
ciphers = get_config()->ciphers.get();
|
ciphers = tlsconf.ciphers.get();
|
||||||
} else {
|
} else {
|
||||||
ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST;
|
ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST;
|
||||||
}
|
}
|
||||||
|
@ -525,9 +527,9 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file
|
||||||
|
|
||||||
#endif // OPENSSL_NO_EC
|
#endif // OPENSSL_NO_EC
|
||||||
|
|
||||||
if (get_config()->dh_param_file) {
|
if (tlsconf.dh_param_file) {
|
||||||
// Read DH parameters from file
|
// Read DH parameters from file
|
||||||
auto bio = BIO_new_file(get_config()->dh_param_file.get(), "r");
|
auto bio = BIO_new_file(tlsconf.dh_param_file.get(), "r");
|
||||||
if (bio == nullptr) {
|
if (bio == nullptr) {
|
||||||
LOG(FATAL) << "BIO_new_file() failed: "
|
LOG(FATAL) << "BIO_new_file() failed: "
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
|
@ -546,7 +548,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file
|
||||||
|
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||||
if (get_config()->private_key_passwd) {
|
if (tlsconf.private_key_passwd) {
|
||||||
SSL_CTX_set_default_passwd_cb(ssl_ctx, ssl_pem_passwd_cb);
|
SSL_CTX_set_default_passwd_cb(ssl_ctx, ssl_pem_passwd_cb);
|
||||||
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)get_config());
|
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)get_config());
|
||||||
}
|
}
|
||||||
|
@ -576,14 +578,13 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
if (get_config()->verify_client) {
|
if (tlsconf.client_verify.enabled) {
|
||||||
if (get_config()->verify_client_cacert) {
|
if (tlsconf.client_verify.cacert) {
|
||||||
if (SSL_CTX_load_verify_locations(
|
if (SSL_CTX_load_verify_locations(
|
||||||
ssl_ctx, get_config()->verify_client_cacert.get(), nullptr) !=
|
ssl_ctx, tlsconf.client_verify.cacert.get(), nullptr) != 1) {
|
||||||
1) {
|
|
||||||
|
|
||||||
LOG(FATAL) << "Could not load trusted ca certificates from "
|
LOG(FATAL) << "Could not load trusted ca certificates from "
|
||||||
<< get_config()->verify_client_cacert.get() << ": "
|
<< tlsconf.client_verify.cacert.get() << ": "
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
@ -591,11 +592,10 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file
|
||||||
// error even though it returns success. See
|
// error even though it returns success. See
|
||||||
// http://forum.nginx.org/read.php?29,242540
|
// http://forum.nginx.org/read.php?29,242540
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
auto list =
|
auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.get());
|
||||||
SSL_load_client_CA_file(get_config()->verify_client_cacert.get());
|
|
||||||
if (!list) {
|
if (!list) {
|
||||||
LOG(FATAL) << "Could not load ca certificates from "
|
LOG(FATAL) << "Could not load ca certificates from "
|
||||||
<< get_config()->verify_client_cacert.get() << ": "
|
<< tlsconf.client_verify.cacert.get() << ": "
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
@ -656,11 +656,13 @@ SSL_CTX *create_ssl_client_context(
|
||||||
SSL_OP_NO_COMPRESSION |
|
SSL_OP_NO_COMPRESSION |
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
|
||||||
|
|
||||||
SSL_CTX_set_options(ssl_ctx, ssl_opts | get_config()->tls_proto_mask);
|
auto &tlsconf = get_config()->tls;
|
||||||
|
|
||||||
|
SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask);
|
||||||
|
|
||||||
const char *ciphers;
|
const char *ciphers;
|
||||||
if (get_config()->ciphers) {
|
if (tlsconf.ciphers) {
|
||||||
ciphers = get_config()->ciphers.get();
|
ciphers = tlsconf.ciphers.get();
|
||||||
} else {
|
} else {
|
||||||
ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST;
|
ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST;
|
||||||
}
|
}
|
||||||
|
@ -678,44 +680,44 @@ SSL_CTX *create_ssl_client_context(
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->cacert) {
|
if (tlsconf.cacert) {
|
||||||
if (SSL_CTX_load_verify_locations(ssl_ctx, get_config()->cacert.get(),
|
if (SSL_CTX_load_verify_locations(ssl_ctx, tlsconf.cacert.get(), nullptr) !=
|
||||||
nullptr) != 1) {
|
1) {
|
||||||
|
|
||||||
LOG(FATAL) << "Could not load trusted ca certificates from "
|
LOG(FATAL) << "Could not load trusted ca certificates from "
|
||||||
<< get_config()->cacert.get() << ": "
|
<< tlsconf.cacert.get() << ": "
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->client_private_key_file) {
|
if (tlsconf.client.private_key_file) {
|
||||||
#ifndef HAVE_NEVERBLEED
|
#ifndef HAVE_NEVERBLEED
|
||||||
if (SSL_CTX_use_PrivateKey_file(ssl_ctx,
|
if (SSL_CTX_use_PrivateKey_file(ssl_ctx,
|
||||||
get_config()->client_private_key_file.get(),
|
tlsconf.client.private_key_file.get(),
|
||||||
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 "
|
||||||
<< get_config()->client_private_key_file.get() << ": "
|
<< tlsconf.client.private_key_file.get() << ": "
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
#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(
|
if (neverbleed_load_private_key_file(nb, ssl_ctx,
|
||||||
nb, ssl_ctx, get_config()->client_private_key_file.get(),
|
tlsconf.client.private_key_file.get(),
|
||||||
errbuf.data()) != 1) {
|
errbuf.data()) != 1) {
|
||||||
LOG(FATAL) << "neverbleed_load_private_key_file failed: "
|
LOG(FATAL) << "neverbleed_load_private_key_file failed: "
|
||||||
<< errbuf.data();
|
<< errbuf.data();
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
}
|
}
|
||||||
if (get_config()->client_cert_file) {
|
if (tlsconf.client.cert_file) {
|
||||||
if (SSL_CTX_use_certificate_chain_file(
|
if (SSL_CTX_use_certificate_chain_file(
|
||||||
ssl_ctx, get_config()->client_cert_file.get()) != 1) {
|
ssl_ctx, tlsconf.client.cert_file.get()) != 1) {
|
||||||
|
|
||||||
LOG(FATAL) << "Could not load client certificate from "
|
LOG(FATAL) << "Could not load client certificate from "
|
||||||
<< get_config()->client_cert_file.get() << ": "
|
<< tlsconf.client.cert_file.get() << ": "
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
@ -971,9 +973,11 @@ int check_cert(SSL *ssl, const DownstreamAddr *addr) {
|
||||||
<< X509_verify_cert_error_string(verify_res);
|
<< X509_verify_cert_error_string(verify_res);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
auto hostname = !get_config()->backend_tls_sni_name.empty()
|
|
||||||
? StringRef(get_config()->backend_tls_sni_name)
|
auto &backend_sni_name = get_config()->tls.backend_sni_name;
|
||||||
: StringRef(addr->host);
|
|
||||||
|
auto hostname = !backend_sni_name.empty() ? StringRef(backend_sni_name)
|
||||||
|
: StringRef(addr->host);
|
||||||
if (verify_hostname(cert, hostname.c_str(), hostname.size(), &addr->addr) !=
|
if (verify_hostname(cert, hostname.c_str(), hostname.size(), &addr->addr) !=
|
||||||
0) {
|
0) {
|
||||||
LOG(ERROR) << "Certificate verification failed: hostname does not match";
|
LOG(ERROR) << "Certificate verification failed: hostname does not match";
|
||||||
|
@ -1214,8 +1218,10 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ssl_ctx = ssl::create_ssl_context(get_config()->private_key_file.get(),
|
auto &tlsconf = get_config()->tls;
|
||||||
get_config()->cert_file.get()
|
|
||||||
|
auto ssl_ctx = ssl::create_ssl_context(tlsconf.private_key_file.get(),
|
||||||
|
tlsconf.cert_file.get()
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
,
|
,
|
||||||
nb
|
nb
|
||||||
|
@ -1224,7 +1230,7 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
||||||
|
|
||||||
all_ssl_ctx.push_back(ssl_ctx);
|
all_ssl_ctx.push_back(ssl_ctx);
|
||||||
|
|
||||||
if (get_config()->subcerts.empty()) {
|
if (tlsconf.subcerts.empty()) {
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1234,7 +1240,7 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &keycert : get_config()->subcerts) {
|
for (auto &keycert : tlsconf.subcerts) {
|
||||||
auto ssl_ctx =
|
auto ssl_ctx =
|
||||||
ssl::create_ssl_context(keycert.first.c_str(), keycert.second.c_str()
|
ssl::create_ssl_context(keycert.first.c_str(), keycert.second.c_str()
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
|
@ -1250,8 +1256,8 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssl::cert_lookup_tree_add_cert_from_file(
|
if (ssl::cert_lookup_tree_add_cert_from_file(cert_tree, ssl_ctx,
|
||||||
cert_tree, ssl_ctx, get_config()->cert_file.get()) == -1) {
|
tlsconf.cert_file.get()) == -1) {
|
||||||
LOG(FATAL) << "Failed to add default certificate.";
|
LOG(FATAL) << "Failed to add default certificate.";
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
@ -1284,7 +1290,7 @@ SSL_CTX *setup_client_ssl_context(
|
||||||
}
|
}
|
||||||
|
|
||||||
CertLookupTree *create_cert_lookup_tree() {
|
CertLookupTree *create_cert_lookup_tree() {
|
||||||
if (get_config()->upstream_no_tls || get_config()->subcerts.empty()) {
|
if (get_config()->upstream_no_tls || get_config()->tls.subcerts.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return new ssl::CertLookupTree();
|
return new ssl::CertLookupTree();
|
||||||
|
|
|
@ -83,9 +83,11 @@ Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
|
||||||
ev_timer_init(&mcpool_clear_timer_, mcpool_clear_cb, 0., 0.);
|
ev_timer_init(&mcpool_clear_timer_, mcpool_clear_cb, 0., 0.);
|
||||||
mcpool_clear_timer_.data = this;
|
mcpool_clear_timer_.data = this;
|
||||||
|
|
||||||
if (get_config()->session_cache_memcached_host) {
|
auto &session_cacheconf = get_config()->tls.session_cache;
|
||||||
|
|
||||||
|
if (session_cacheconf.memcached.host) {
|
||||||
session_cache_memcached_dispatcher_ = make_unique<MemcachedDispatcher>(
|
session_cache_memcached_dispatcher_ = make_unique<MemcachedDispatcher>(
|
||||||
&get_config()->session_cache_memcached_addr, loop);
|
&session_cacheconf.memcached.addr, loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->downstream_proto == PROTO_HTTP2) {
|
if (get_config()->downstream_proto == PROTO_HTTP2) {
|
||||||
|
|
|
@ -170,7 +170,7 @@ void ipc_readcb(struct ev_loop *loop, ev_io *w, int revents) {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int generate_ticket_key(TicketKey &ticket_key) {
|
int generate_ticket_key(TicketKey &ticket_key) {
|
||||||
ticket_key.cipher = get_config()->tls_ticket_key_cipher;
|
ticket_key.cipher = get_config()->tls.ticket.cipher;
|
||||||
ticket_key.hmac = EVP_sha256();
|
ticket_key.hmac = EVP_sha256();
|
||||||
ticket_key.hmac_keylen = EVP_MD_size(ticket_key.hmac);
|
ticket_key.hmac_keylen = EVP_MD_size(ticket_key.hmac);
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ void renew_ticket_key_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
||||||
|
|
||||||
auto max_tickets =
|
auto max_tickets =
|
||||||
static_cast<size_t>(std::chrono::duration_cast<std::chrono::hours>(
|
static_cast<size_t>(std::chrono::duration_cast<std::chrono::hours>(
|
||||||
get_config()->tls_session_timeout).count());
|
get_config()->tls.session_timeout).count());
|
||||||
|
|
||||||
new_keys.resize(std::min(max_tickets, old_keys.size() + 1));
|
new_keys.resize(std::min(max_tickets, old_keys.size() + 1));
|
||||||
std::copy_n(std::begin(old_keys), new_keys.size() - 1,
|
std::copy_n(std::begin(old_keys), new_keys.size() - 1,
|
||||||
|
@ -297,14 +297,16 @@ void memcached_get_ticket_key_cb(struct ev_loop *loop, ev_timer *w,
|
||||||
auto end = p + value.size();
|
auto end = p + value.size();
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|
||||||
|
auto &ticketconf = get_config()->tls.ticket;
|
||||||
|
|
||||||
size_t expectedlen;
|
size_t expectedlen;
|
||||||
size_t enc_keylen;
|
size_t enc_keylen;
|
||||||
size_t hmac_keylen;
|
size_t hmac_keylen;
|
||||||
if (get_config()->tls_ticket_key_cipher == EVP_aes_128_cbc()) {
|
if (ticketconf.cipher == EVP_aes_128_cbc()) {
|
||||||
expectedlen = 48;
|
expectedlen = 48;
|
||||||
enc_keylen = 16;
|
enc_keylen = 16;
|
||||||
hmac_keylen = 16;
|
hmac_keylen = 16;
|
||||||
} else if (get_config()->tls_ticket_key_cipher == EVP_aes_256_cbc()) {
|
} else if (ticketconf.cipher == EVP_aes_256_cbc()) {
|
||||||
expectedlen = 80;
|
expectedlen = 80;
|
||||||
enc_keylen = 32;
|
enc_keylen = 32;
|
||||||
hmac_keylen = 32;
|
hmac_keylen = 32;
|
||||||
|
@ -335,7 +337,7 @@ void memcached_get_ticket_key_cb(struct ev_loop *loop, ev_timer *w,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto key = TicketKey();
|
auto key = TicketKey();
|
||||||
key.cipher = get_config()->tls_ticket_key_cipher;
|
key.cipher = ticketconf.cipher;
|
||||||
key.hmac = EVP_sha256();
|
key.hmac = EVP_sha256();
|
||||||
key.hmac_keylen = hmac_keylen;
|
key.hmac_keylen = hmac_keylen;
|
||||||
|
|
||||||
|
@ -423,10 +425,11 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
||||||
|
|
||||||
ev_timer renew_ticket_key_timer;
|
ev_timer renew_ticket_key_timer;
|
||||||
if (!get_config()->upstream_no_tls) {
|
if (!get_config()->upstream_no_tls) {
|
||||||
if (get_config()->tls_ticket_key_memcached_host) {
|
auto &ticketconf = get_config()->tls.ticket;
|
||||||
|
|
||||||
|
if (ticketconf.memcached.host) {
|
||||||
conn_handler.set_tls_ticket_key_memcached_dispatcher(
|
conn_handler.set_tls_ticket_key_memcached_dispatcher(
|
||||||
make_unique<MemcachedDispatcher>(
|
make_unique<MemcachedDispatcher>(&ticketconf.memcached.addr, loop));
|
||||||
&get_config()->tls_ticket_key_memcached_addr, loop));
|
|
||||||
|
|
||||||
ev_timer_init(&renew_ticket_key_timer, memcached_get_ticket_key_cb, 0.,
|
ev_timer_init(&renew_ticket_key_timer, memcached_get_ticket_key_cb, 0.,
|
||||||
0.);
|
0.);
|
||||||
|
@ -435,8 +438,8 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
||||||
memcached_get_ticket_key_cb(loop, &renew_ticket_key_timer, 0);
|
memcached_get_ticket_key_cb(loop, &renew_ticket_key_timer, 0);
|
||||||
} else {
|
} else {
|
||||||
bool auto_tls_ticket_key = true;
|
bool auto_tls_ticket_key = true;
|
||||||
if (!get_config()->tls_ticket_key_files.empty()) {
|
if (!ticketconf.files.empty()) {
|
||||||
if (!get_config()->tls_ticket_key_cipher_given) {
|
if (!ticketconf.cipher_given) {
|
||||||
LOG(WARN)
|
LOG(WARN)
|
||||||
<< "It is strongly recommended to specify "
|
<< "It is strongly recommended to specify "
|
||||||
"--tls-ticket-key-cipher=aes-128-cbc (or "
|
"--tls-ticket-key-cipher=aes-128-cbc (or "
|
||||||
|
@ -446,8 +449,7 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
||||||
"becomes aes-256-cbc";
|
"becomes aes-256-cbc";
|
||||||
}
|
}
|
||||||
auto ticket_keys = read_tls_ticket_key_file(
|
auto ticket_keys = read_tls_ticket_key_file(
|
||||||
get_config()->tls_ticket_key_files,
|
ticketconf.files, ticketconf.cipher, EVP_sha256());
|
||||||
get_config()->tls_ticket_key_cipher, EVP_sha256());
|
|
||||||
if (!ticket_keys) {
|
if (!ticket_keys) {
|
||||||
LOG(WARN) << "Use internal session ticket key generator";
|
LOG(WARN) << "Use internal session ticket key generator";
|
||||||
} else {
|
} else {
|
||||||
|
@ -512,7 +514,7 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
||||||
ipcev.data = &conn_handler;
|
ipcev.data = &conn_handler;
|
||||||
ev_io_start(loop, &ipcev);
|
ev_io_start(loop, &ipcev);
|
||||||
|
|
||||||
if (!get_config()->upstream_no_tls && !get_config()->no_ocsp) {
|
if (!get_config()->upstream_no_tls && !get_config()->tls.ocsp.disabled) {
|
||||||
conn_handler.proceed_next_cert_ocsp();
|
conn_handler.proceed_next_cert_ocsp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue