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
|
||||
mod_config()->backlog = -1;
|
||||
mod_config()->ciphers = nullptr;
|
||||
mod_config()->honor_cipher_order = false;
|
||||
mod_config()->http2_proxy = false;
|
||||
mod_config()->http2_bridge = false;
|
||||
mod_config()->client_proxy = false;
|
||||
|
@ -616,12 +615,7 @@ Timeout:
|
|||
|
||||
SSL/TLS:
|
||||
--ciphers=<SUITE> Set allowed cipher list. The format of the
|
||||
string is described in OpenSSL ciphers(1). If
|
||||
this option is used, --honor-cipher-order is
|
||||
implicitly enabled.
|
||||
--honor-cipher-order
|
||||
Honor server cipher order, giving the ability to
|
||||
mitigate BEAST attacks.
|
||||
string is described in OpenSSL ciphers(1).
|
||||
-k, --insecure
|
||||
Don't verify backend server's certificate if -p,
|
||||
--client or --http2-bridge are given and
|
||||
|
@ -859,7 +853,6 @@ int main(int argc, char **argv)
|
|||
{"backend-no-tls", no_argument, &flag, 27},
|
||||
{"frontend-no-tls", no_argument, &flag, 29},
|
||||
{"backend-tls-sni-field", required_argument, &flag, 31},
|
||||
{"honor-cipher-order", no_argument, &flag, 32},
|
||||
{"dh-param-file", required_argument, &flag, 33},
|
||||
{"read-rate", required_argument, &flag, 34},
|
||||
{"read-burst", required_argument, &flag, 35},
|
||||
|
@ -1051,10 +1044,6 @@ int main(int argc, char **argv)
|
|||
// --backend-tls-sni-field
|
||||
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS_SNI_FIELD, optarg);
|
||||
break;
|
||||
case 32:
|
||||
// --honor-cipher-order
|
||||
cmdcfgs.emplace_back(SHRPX_OPT_HONOR_CIPHER_ORDER, "yes");
|
||||
break;
|
||||
case 33:
|
||||
// --dh-param-file
|
||||
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_BACKLOG[] = "backlog";
|
||||
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_INSECURE[] = "insecure";
|
||||
const char SHRPX_OPT_CACERT[] = "cacert";
|
||||
|
@ -572,12 +571,6 @@ int parse_config(const char *opt, const char *optarg)
|
|||
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)) {
|
||||
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_BACKLOG[];
|
||||
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_INSECURE[];
|
||||
extern const char SHRPX_OPT_CACERT[];
|
||||
|
@ -245,7 +244,6 @@ struct Config {
|
|||
bool syslog;
|
||||
// This member finally decides syslog is used or not
|
||||
bool use_syslog;
|
||||
bool honor_cipher_order;
|
||||
bool client;
|
||||
// true if --client or --client-proxy are enabled.
|
||||
bool client_mode;
|
||||
|
|
|
@ -250,14 +250,14 @@ SSL_CTX* create_ssl_context(const char *private_key_file,
|
|||
const char *ciphers;
|
||||
if(get_config()->ciphers) {
|
||||
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 {
|
||||
ciphers = "HIGH:!aNULL:!eNULL";
|
||||
if(get_config()->honor_cipher_order) {
|
||||
// Recommended general purpose cipher by mozilla.
|
||||
// https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||
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) {
|
||||
LOG(FATAL) << "SSL_CTX_set_cipher_list " << ciphers << " failed: "
|
||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||
|
@ -907,6 +907,40 @@ bool in_proto_list(const std::vector<char*>& protos,
|
|||
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)
|
||||
{
|
||||
auto tls_ver = SSL_version(ssl);
|
||||
|
@ -921,8 +955,46 @@ bool check_http2_requirement(SSL *ssl)
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO Figure out that ECDHE or DHE was negotiated and their key
|
||||
// size. SSL_get_server_tmp_key() cannot be used on server side.
|
||||
auto cipher = SSL_get_current_cipher(ssl);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue