nghttpx: Add --no-http2-cipher-black-list to allow black listed cipher suite
This commit is contained in:
parent
eec409dba7
commit
8741503db1
|
@ -109,7 +109,8 @@ OPTIONS = [
|
||||||
"forwarded-by",
|
"forwarded-by",
|
||||||
"forwarded-for",
|
"forwarded-for",
|
||||||
"response-header-field-buffer",
|
"response-header-field-buffer",
|
||||||
"max-response-header-fields"
|
"max-response-header-fields",
|
||||||
|
"no-http2-cipher-black-list"
|
||||||
]
|
]
|
||||||
|
|
||||||
LOGVARS = [
|
LOGVARS = [
|
||||||
|
|
|
@ -1571,6 +1571,10 @@ SSL/TLS:
|
||||||
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"(
|
||||||
|
--no-http2-cipher-black-list
|
||||||
|
Allow black listed cipher suite on HTTP/2 connection.
|
||||||
|
See https://tools.ietf.org/html/rfc7540#appendix-A for
|
||||||
|
the complete HTTP/2 cipher suites black list.
|
||||||
|
|
||||||
HTTP/2 and SPDY:
|
HTTP/2 and SPDY:
|
||||||
-c, --http2-max-concurrent-streams=<N>
|
-c, --http2-max-concurrent-streams=<N>
|
||||||
|
@ -2367,6 +2371,7 @@ int main(int argc, char **argv) {
|
||||||
{SHRPX_OPT_FORWARDED_FOR, required_argument, &flag, 100},
|
{SHRPX_OPT_FORWARDED_FOR, required_argument, &flag, 100},
|
||||||
{SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER, required_argument, &flag, 101},
|
{SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER, required_argument, &flag, 101},
|
||||||
{SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS, required_argument, &flag, 102},
|
{SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS, required_argument, &flag, 102},
|
||||||
|
{SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST, no_argument, &flag, 103},
|
||||||
{nullptr, 0, nullptr, 0}};
|
{nullptr, 0, nullptr, 0}};
|
||||||
|
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
@ -2804,6 +2809,10 @@ int main(int argc, char **argv) {
|
||||||
// --max-response-header-fields
|
// --max-response-header-fields
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS, optarg);
|
cmdcfgs.emplace_back(SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS, optarg);
|
||||||
break;
|
break;
|
||||||
|
case 103:
|
||||||
|
// --no-http2-cipher-black-list
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST, "yes");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -729,6 +729,7 @@ enum {
|
||||||
SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS,
|
SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS,
|
||||||
SHRPX_OPTID_MRUBY_FILE,
|
SHRPX_OPTID_MRUBY_FILE,
|
||||||
SHRPX_OPTID_NO_HOST_REWRITE,
|
SHRPX_OPTID_NO_HOST_REWRITE,
|
||||||
|
SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST,
|
||||||
SHRPX_OPTID_NO_LOCATION_REWRITE,
|
SHRPX_OPTID_NO_LOCATION_REWRITE,
|
||||||
SHRPX_OPTID_NO_OCSP,
|
SHRPX_OPTID_NO_OCSP,
|
||||||
SHRPX_OPTID_NO_SERVER_PUSH,
|
SHRPX_OPTID_NO_SERVER_PUSH,
|
||||||
|
@ -1268,6 +1269,9 @@ int option_lookup_token(const char *name, size_t namelen) {
|
||||||
if (util::strieq_l("backend-keep-alive-timeou", name, 25)) {
|
if (util::strieq_l("backend-keep-alive-timeou", name, 25)) {
|
||||||
return SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT;
|
return SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
if (util::strieq_l("no-http2-cipher-black-lis", name, 25)) {
|
||||||
|
return SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2188,6 +2192,10 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST:
|
||||||
|
mod_config()->tls.no_http2_cipher_black_list = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
|
return 0;
|
||||||
case SHRPX_OPTID_CONF:
|
case SHRPX_OPTID_CONF:
|
||||||
LOG(WARN) << "conf: ignored";
|
LOG(WARN) << "conf: ignored";
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,8 @@ constexpr char SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER[] =
|
||||||
"response-header-field-buffer";
|
"response-header-field-buffer";
|
||||||
constexpr char SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS[] =
|
constexpr char SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS[] =
|
||||||
"max-response-header-fields";
|
"max-response-header-fields";
|
||||||
|
constexpr char SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST[] =
|
||||||
|
"no-http2-cipher-black-list";
|
||||||
|
|
||||||
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
|
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
|
||||||
|
|
||||||
|
@ -396,6 +398,7 @@ struct TLSConfig {
|
||||||
std::unique_ptr<char[]> ciphers;
|
std::unique_ptr<char[]> ciphers;
|
||||||
std::unique_ptr<char[]> cacert;
|
std::unique_ptr<char[]> cacert;
|
||||||
bool insecure;
|
bool insecure;
|
||||||
|
bool no_http2_cipher_black_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HttpConfig {
|
struct HttpConfig {
|
||||||
|
|
|
@ -488,10 +488,17 @@ int Connection::check_http2_requirement() {
|
||||||
!util::check_h2_is_selected(next_proto, next_proto_len)) {
|
!util::check_h2_is_selected(next_proto, next_proto_len)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!nghttp2::ssl::check_http2_requirement(tls.ssl)) {
|
if (!nghttp2::ssl::check_http2_tls_version(tls.ssl)) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
LOG(INFO) << "TLSv1.2 and/or black listed cipher suite was negotiated. "
|
LOG(INFO) << "TLSv1.2 was not negotiated. HTTP/2 must not be used.";
|
||||||
"HTTP/2 must not be used.";
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!get_config()->tls.no_http2_cipher_black_list &&
|
||||||
|
nghttp2::ssl::check_http2_cipher_black_list(tls.ssl)) {
|
||||||
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
LOG(INFO) << "The negotiated cipher suite is in HTTP/2 cipher suite "
|
||||||
|
"black list. HTTP/2 must not be used.";
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
25
src/ssl.cc
25
src/ssl.cc
|
@ -397,19 +397,10 @@ enum {
|
||||||
TLS_PSK_WITH_AES_256_CCM_8 = 0xC0A9u,
|
TLS_PSK_WITH_AES_256_CCM_8 = 0xC0A9u,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool check_http2_requirement(SSL *ssl) {
|
bool check_http2_cipher_black_list(SSL *ssl) {
|
||||||
auto tls_ver = SSL_version(ssl);
|
|
||||||
|
|
||||||
switch (tls_ver) {
|
|
||||||
case TLS1_2_VERSION:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cipher = SSL_get_current_cipher(ssl);
|
auto cipher = SSL_get_current_cipher(ssl);
|
||||||
|
|
||||||
// Cipher suites in RFC 7540 balck list are not allowed in HTTP/2.
|
// Cipher suites in RFC 7540 black list are not allowed in HTTP/2.
|
||||||
switch (SSL_CIPHER_get_id(cipher) & 0xffffu) {
|
switch (SSL_CIPHER_get_id(cipher) & 0xffffu) {
|
||||||
case TLS_NULL_WITH_NULL_NULL:
|
case TLS_NULL_WITH_NULL_NULL:
|
||||||
case TLS_RSA_WITH_NULL_MD5:
|
case TLS_RSA_WITH_NULL_MD5:
|
||||||
|
@ -687,10 +678,20 @@ bool check_http2_requirement(SSL *ssl) {
|
||||||
case TLS_PSK_WITH_AES_256_CCM:
|
case TLS_PSK_WITH_AES_256_CCM:
|
||||||
case TLS_PSK_WITH_AES_128_CCM_8:
|
case TLS_PSK_WITH_AES_128_CCM_8:
|
||||||
case TLS_PSK_WITH_AES_256_CCM_8:
|
case TLS_PSK_WITH_AES_256_CCM_8:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
bool check_http2_tls_version(SSL *ssl) {
|
||||||
|
auto tls_ver = SSL_version(ssl);
|
||||||
|
|
||||||
|
return tls_ver == TLS1_2_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_http2_requirement(SSL *ssl) {
|
||||||
|
return check_http2_tls_version(ssl) && !check_http2_cipher_black_list(ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void libssl_init() {
|
void libssl_init() {
|
||||||
|
|
|
@ -59,6 +59,13 @@ struct TLSSessionInfo {
|
||||||
|
|
||||||
TLSSessionInfo *get_tls_session_info(TLSSessionInfo *tls_info, SSL *ssl);
|
TLSSessionInfo *get_tls_session_info(TLSSessionInfo *tls_info, SSL *ssl);
|
||||||
|
|
||||||
|
// Returns true iff the negotiated protocol is TLSv1.2.
|
||||||
|
bool check_http2_tls_version(SSL *ssl);
|
||||||
|
|
||||||
|
// Returns true iff the negotiated cipher suite is in HTTP/2 cipher
|
||||||
|
// black list.
|
||||||
|
bool check_http2_cipher_black_list(SSL *ssl);
|
||||||
|
|
||||||
// Returns true if SSL/TLS requirement for HTTP/2 is fulfilled.
|
// Returns true if SSL/TLS requirement for HTTP/2 is fulfilled.
|
||||||
// To fulfill the requirement, the following 2 terms must be hold:
|
// To fulfill the requirement, the following 2 terms must be hold:
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue