diff --git a/gennghttpxfun.py b/gennghttpxfun.py index 4d4fb7e4..cac3a548 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -155,6 +155,7 @@ OPTIONS = [ "frontend-keep-alive-timeout", "psk-secrets", "client-psk-secrets", + "client-no-http2-cipher-black-list", ] LOGVARS = [ diff --git a/src/shrpx.cc b/src/shrpx.cc index c31ae514..4dc79b70 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -2091,9 +2091,15 @@ SSL/TLS: Default: )" << util::duration_str(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. + Allow black listed cipher suite on frontend HTTP/2 + connection. See + https://tools.ietf.org/html/rfc7540#appendix-A for the + complete HTTP/2 cipher suites black list. + --client-no-http2-cipher-black-list + Allow black listed cipher suite on backend HTTP/2 + connection. See + https://tools.ietf.org/html/rfc7540#appendix-A for the + complete HTTP/2 cipher suites black list. --tls-sct-dir= Specifies the directory where *.sct files exist. All *.sct files in are read, and sent as @@ -3096,6 +3102,8 @@ int main(int argc, char **argv) { &flag, 146}, {SHRPX_OPT_PSK_SECRETS.c_str(), required_argument, &flag, 147}, {SHRPX_OPT_CLIENT_PSK_SECRETS.c_str(), required_argument, &flag, 148}, + {SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST.c_str(), no_argument, + &flag, 149}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -3794,6 +3802,11 @@ int main(int argc, char **argv) { // --client-psk-secrets cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PSK_SECRETS, StringRef{optarg}); break; + case 149: + // --client-no-http2-cipher-black-list + cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST, + StringRef::from_lit("yes")); + break; default: break; } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 4bd4efdf..4fc3f841 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -2004,6 +2004,11 @@ int option_lookup_token(const char *name, size_t namelen) { return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL; } break; + case 't': + if (util::strieq_l("client-no-http2-cipher-black-lis", name, 32)) { + return SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST; + } + break; } break; case 34: @@ -3274,6 +3279,11 @@ int parse_config(Config *config, int optid, const StringRef &opt, return parse_psk_secrets(config, optarg); case SHRPX_OPTID_CLIENT_PSK_SECRETS: return parse_client_psk_secrets(config, optarg); + case SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST: + config->tls.client.no_http2_cipher_black_list = + util::strieq_l("yes", optarg); + + return 0; case SHRPX_OPTID_CONF: LOG(WARN) << "conf: ignored"; diff --git a/src/shrpx_config.h b/src/shrpx_config.h index 118ecc1a..0d9c8c81 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -322,6 +322,8 @@ constexpr auto SHRPX_OPT_FRONTEND_KEEP_ALIVE_TIMEOUT = constexpr auto SHRPX_OPT_PSK_SECRETS = StringRef::from_lit("psk-secrets"); constexpr auto SHRPX_OPT_CLIENT_PSK_SECRETS = StringRef::from_lit("client-psk-secrets"); +constexpr auto SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST = + StringRef::from_lit("client-no-http2-cipher-black-list"); constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; @@ -556,6 +558,7 @@ struct TLSConfig { } psk; StringRef private_key_file; StringRef cert_file; + bool no_http2_cipher_black_list; } client; // PSK secrets. The key is identity, and the associated value is @@ -924,6 +927,7 @@ enum { SHRPX_OPTID_CIPHERS, SHRPX_OPTID_CLIENT, SHRPX_OPTID_CLIENT_CERT_FILE, + SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST, SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE, SHRPX_OPTID_CLIENT_PROXY, SHRPX_OPTID_CLIENT_PSK_SECRETS, diff --git a/src/shrpx_connection.cc b/src/shrpx_connection.cc index a10f4358..914c7ccb 100644 --- a/src/shrpx_connection.cc +++ b/src/shrpx_connection.cc @@ -141,7 +141,10 @@ void Connection::disconnect() { void Connection::prepare_client_handshake() { SSL_set_connect_state(tls.ssl); } -void Connection::prepare_server_handshake() { SSL_set_accept_state(tls.ssl); } +void Connection::prepare_server_handshake() { + SSL_set_accept_state(tls.ssl); + tls.server_handshake = true; +} // BIO implementation is inspired by openldap implementation: // http://www.openldap.org/devel/cvsweb.cgi/~checkout~/libraries/libldap/tls_o.c @@ -530,7 +533,15 @@ int Connection::check_http2_requirement() { } return -1; } - if (!get_config()->tls.no_http2_cipher_black_list && + + auto check_black_list = false; + if (tls.server_handshake) { + check_black_list = !get_config()->tls.no_http2_cipher_black_list; + } else { + check_black_list = !get_config()->tls.client.no_http2_cipher_black_list; + } + + if (check_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 " diff --git a/src/shrpx_connection.h b/src/shrpx_connection.h index 5dc1c37e..990a85ed 100644 --- a/src/shrpx_connection.h +++ b/src/shrpx_connection.h @@ -64,6 +64,8 @@ struct TLSConnection { int handshake_state; bool initial_handshake_done; bool reneg_started; + // true if ssl is prepared to do handshake as server. + bool server_handshake; }; struct TCPHint {