nghttpx: Only allow DHE, ECDHE + AEAD ciphers for HTTP/2
Cipher suites are chosen by DHE and ECDHE ciphers + GCM (AEAD). Now default cipher list is the one recommended by Mozilla web site. The --honor-cipher-order option is removed and now it is always assumed.
This commit is contained in:
parent
5f5b5378c9
commit
7b0ed5d9bd
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import csv
|
||||||
|
|
||||||
|
pat = re.compile(r'\ATLS_(?:ECDHE|DHE)_.*_GCM')
|
||||||
|
|
||||||
|
ciphers = []
|
||||||
|
for hl, name, _, _ in csv.reader(sys.stdin):
|
||||||
|
if not pat.match(name):
|
||||||
|
continue
|
||||||
|
|
||||||
|
high, low = hl.split(',')
|
||||||
|
|
||||||
|
id = high + low[2:] + 'u'
|
||||||
|
ciphers.append((id, name))
|
||||||
|
|
||||||
|
print '''\
|
||||||
|
enum {'''
|
||||||
|
|
||||||
|
for id, name in ciphers:
|
||||||
|
print '{} = {},'.format(name, id)
|
||||||
|
|
||||||
|
print '''\
|
||||||
|
};
|
||||||
|
'''
|
||||||
|
|
||||||
|
for id, name in ciphers:
|
||||||
|
print '''\
|
||||||
|
case {}:'''.format(name)
|
13
src/shrpx.cc
13
src/shrpx.cc
|
@ -407,7 +407,6 @@ void fill_default_config()
|
||||||
// Default accept() backlog
|
// Default accept() backlog
|
||||||
mod_config()->backlog = -1;
|
mod_config()->backlog = -1;
|
||||||
mod_config()->ciphers = nullptr;
|
mod_config()->ciphers = nullptr;
|
||||||
mod_config()->honor_cipher_order = false;
|
|
||||||
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;
|
||||||
|
@ -616,12 +615,7 @@ Timeout:
|
||||||
|
|
||||||
SSL/TLS:
|
SSL/TLS:
|
||||||
--ciphers=<SUITE> Set allowed cipher list. The format of the
|
--ciphers=<SUITE> Set allowed cipher list. The format of the
|
||||||
string is described in OpenSSL ciphers(1). If
|
string is described in OpenSSL ciphers(1).
|
||||||
this option is used, --honor-cipher-order is
|
|
||||||
implicitly enabled.
|
|
||||||
--honor-cipher-order
|
|
||||||
Honor server cipher order, giving the ability to
|
|
||||||
mitigate BEAST attacks.
|
|
||||||
-k, --insecure
|
-k, --insecure
|
||||||
Don't verify backend server's certificate if -p,
|
Don't verify backend server's certificate if -p,
|
||||||
--client or --http2-bridge are given and
|
--client or --http2-bridge are given and
|
||||||
|
@ -859,7 +853,6 @@ int main(int argc, char **argv)
|
||||||
{"backend-no-tls", no_argument, &flag, 27},
|
{"backend-no-tls", no_argument, &flag, 27},
|
||||||
{"frontend-no-tls", no_argument, &flag, 29},
|
{"frontend-no-tls", no_argument, &flag, 29},
|
||||||
{"backend-tls-sni-field", required_argument, &flag, 31},
|
{"backend-tls-sni-field", required_argument, &flag, 31},
|
||||||
{"honor-cipher-order", no_argument, &flag, 32},
|
|
||||||
{"dh-param-file", required_argument, &flag, 33},
|
{"dh-param-file", required_argument, &flag, 33},
|
||||||
{"read-rate", required_argument, &flag, 34},
|
{"read-rate", required_argument, &flag, 34},
|
||||||
{"read-burst", required_argument, &flag, 35},
|
{"read-burst", required_argument, &flag, 35},
|
||||||
|
@ -1051,10 +1044,6 @@ int main(int argc, char **argv)
|
||||||
// --backend-tls-sni-field
|
// --backend-tls-sni-field
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS_SNI_FIELD, optarg);
|
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS_SNI_FIELD, optarg);
|
||||||
break;
|
break;
|
||||||
case 32:
|
|
||||||
// --honor-cipher-order
|
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_HONOR_CIPHER_ORDER, "yes");
|
|
||||||
break;
|
|
||||||
case 33:
|
case 33:
|
||||||
// --dh-param-file
|
// --dh-param-file
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_DH_PARAM_FILE, optarg);
|
cmdcfgs.emplace_back(SHRPX_OPT_DH_PARAM_FILE, optarg);
|
||||||
|
|
|
@ -93,7 +93,6 @@ const char SHRPX_OPT_SYSLOG[] = "syslog";
|
||||||
const char SHRPX_OPT_SYSLOG_FACILITY[] = "syslog-facility";
|
const char SHRPX_OPT_SYSLOG_FACILITY[] = "syslog-facility";
|
||||||
const char SHRPX_OPT_BACKLOG[] = "backlog";
|
const char SHRPX_OPT_BACKLOG[] = "backlog";
|
||||||
const char SHRPX_OPT_CIPHERS[] = "ciphers";
|
const char SHRPX_OPT_CIPHERS[] = "ciphers";
|
||||||
const char SHRPX_OPT_HONOR_CIPHER_ORDER[] = "honor-cipher-order";
|
|
||||||
const char SHRPX_OPT_CLIENT[] = "client";
|
const char SHRPX_OPT_CLIENT[] = "client";
|
||||||
const char SHRPX_OPT_INSECURE[] = "insecure";
|
const char SHRPX_OPT_INSECURE[] = "insecure";
|
||||||
const char SHRPX_OPT_CACERT[] = "cacert";
|
const char SHRPX_OPT_CACERT[] = "cacert";
|
||||||
|
@ -572,12 +571,6 @@ int parse_config(const char *opt, const char *optarg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(util::strieq(opt, SHRPX_OPT_HONOR_CIPHER_ORDER)) {
|
|
||||||
mod_config()->honor_cipher_order = util::strieq(optarg, "yes");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(util::strieq(opt, SHRPX_OPT_CLIENT)) {
|
if(util::strieq(opt, SHRPX_OPT_CLIENT)) {
|
||||||
mod_config()->client = util::strieq(optarg, "yes");
|
mod_config()->client = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,6 @@ extern const char SHRPX_OPT_SYSLOG[];
|
||||||
extern const char SHRPX_OPT_SYSLOG_FACILITY[];
|
extern const char SHRPX_OPT_SYSLOG_FACILITY[];
|
||||||
extern const char SHRPX_OPT_BACKLOG[];
|
extern const char SHRPX_OPT_BACKLOG[];
|
||||||
extern const char SHRPX_OPT_CIPHERS[];
|
extern const char SHRPX_OPT_CIPHERS[];
|
||||||
extern const char SHRPX_OPT_HONOR_CIPHER_ORDER[];
|
|
||||||
extern const char SHRPX_OPT_CLIENT[];
|
extern const char SHRPX_OPT_CLIENT[];
|
||||||
extern const char SHRPX_OPT_INSECURE[];
|
extern const char SHRPX_OPT_INSECURE[];
|
||||||
extern const char SHRPX_OPT_CACERT[];
|
extern const char SHRPX_OPT_CACERT[];
|
||||||
|
@ -245,7 +244,6 @@ struct Config {
|
||||||
bool syslog;
|
bool syslog;
|
||||||
// This member finally decides syslog is used or not
|
// This member finally decides syslog is used or not
|
||||||
bool use_syslog;
|
bool use_syslog;
|
||||||
bool honor_cipher_order;
|
|
||||||
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;
|
||||||
|
|
|
@ -250,14 +250,14 @@ SSL_CTX* create_ssl_context(const char *private_key_file,
|
||||||
const char *ciphers;
|
const char *ciphers;
|
||||||
if(get_config()->ciphers) {
|
if(get_config()->ciphers) {
|
||||||
ciphers = get_config()->ciphers.get();
|
ciphers = get_config()->ciphers.get();
|
||||||
// If ciphers are given, honor its order unconditionally
|
|
||||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
|
||||||
} else {
|
} else {
|
||||||
ciphers = "HIGH:!aNULL:!eNULL";
|
// Recommended general purpose cipher by mozilla.
|
||||||
if(get_config()->honor_cipher_order) {
|
// https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
ciphers = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSL_CTX_set_options(ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||||
|
|
||||||
if(SSL_CTX_set_cipher_list(ssl_ctx, ciphers) == 0) {
|
if(SSL_CTX_set_cipher_list(ssl_ctx, ciphers) == 0) {
|
||||||
LOG(FATAL) << "SSL_CTX_set_cipher_list " << ciphers << " failed: "
|
LOG(FATAL) << "SSL_CTX_set_cipher_list " << ciphers << " failed: "
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
|
@ -907,6 +907,40 @@ bool in_proto_list(const std::vector<char*>& protos,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This enum was generated by mkcipherlist.py
|
||||||
|
enum {
|
||||||
|
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009Eu,
|
||||||
|
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009Fu,
|
||||||
|
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2u,
|
||||||
|
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3u,
|
||||||
|
TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AAu,
|
||||||
|
TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00ABu,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02Bu,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02Cu,
|
||||||
|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02Fu,
|
||||||
|
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030u,
|
||||||
|
TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC052u,
|
||||||
|
TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC053u,
|
||||||
|
TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 = 0xC056u,
|
||||||
|
TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 = 0xC057u,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 = 0xC05Cu,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 = 0xC05Du,
|
||||||
|
TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 = 0xC060u,
|
||||||
|
TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 = 0xC061u,
|
||||||
|
TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 = 0xC06Cu,
|
||||||
|
TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 = 0xC06Du,
|
||||||
|
TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07Cu,
|
||||||
|
TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07Du,
|
||||||
|
TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC080u,
|
||||||
|
TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC081u,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC086u,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC087u,
|
||||||
|
TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08Au,
|
||||||
|
TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08Bu,
|
||||||
|
TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC090u,
|
||||||
|
TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC091u,
|
||||||
|
};
|
||||||
|
|
||||||
bool check_http2_requirement(SSL *ssl)
|
bool check_http2_requirement(SSL *ssl)
|
||||||
{
|
{
|
||||||
auto tls_ver = SSL_version(ssl);
|
auto tls_ver = SSL_version(ssl);
|
||||||
|
@ -921,8 +955,46 @@ bool check_http2_requirement(SSL *ssl)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Figure out that ECDHE or DHE was negotiated and their key
|
auto cipher = SSL_get_current_cipher(ssl);
|
||||||
// size. SSL_get_server_tmp_key() cannot be used on server side.
|
|
||||||
|
switch(SSL_CIPHER_get_id(cipher) & 0xffffu) {
|
||||||
|
// This case labels were generated by mkcipherlist.py
|
||||||
|
case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
|
||||||
|
case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
|
||||||
|
case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
|
||||||
|
case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
|
||||||
|
case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
|
||||||
|
case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
|
||||||
|
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
|
||||||
|
case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
|
||||||
|
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
|
||||||
|
case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
|
||||||
|
case TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256:
|
||||||
|
case TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384:
|
||||||
|
case TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256:
|
||||||
|
case TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384:
|
||||||
|
case TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256:
|
||||||
|
case TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384:
|
||||||
|
case TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256:
|
||||||
|
case TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384:
|
||||||
|
case TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256:
|
||||||
|
case TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384:
|
||||||
|
case TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
|
||||||
|
case TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
|
||||||
|
case TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
|
||||||
|
case TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
|
||||||
|
case TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
|
||||||
|
case TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
|
||||||
|
case TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
|
||||||
|
case TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
|
||||||
|
case TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
|
||||||
|
case TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Check number of bits
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue