[squid-users] [PATCH] SSL: Add suport for EECDH and disable client-initiated renegotiation
Paulo Matias
matias at ufscar.br
Mon May 25 11:30:14 UTC 2015
Hi,
Sorry for getting this sent to squid-users instead of the adequate
mailing list for patches (squid-dev). We have tried to send the
patch to squid-dev without a subscription (as recommended in
http://www.squid-cache.org/Support/mailing-lists.html#squid-dev),
but perhaps the message did not get to the list administrator.
This patch implements two different changes in SSL support:
* Adds support for Ephemeral Elliptic Curve Diffie-Hellman (EECDH)
key exchange, which allows for forward secrecy with better
performance than traditional ephemeral DH.
* Disables client-initiated renegotiation, mitigating a DoS attack
which might be possible with some versions of the OpenSSL library.
We have been warned about this when testing our service with
the Qualys SSL Test (https://www.ssllabs.com/ssltest) back when
it was running in a Debian wheezy system.
Further information is available at:
https://community.qualys.com/blogs/securitylabs/2011/10/31/tls-renegotiation-and-denial-of-service-attacks
Our solution is similar to the one adopted in pureftpd:
https://github.com/jedisct1/pure-ftpd/blob/549e94aaa093a48622efd6d91fdfb3a4236c13f4/src/tls.c#L106
We have been running Squid 3.4.8 in production with a backported
patch for two months. So far, we have no complaints from the users
(60 to 100 users per day) and the server is running stably.
We would be very happy if we could get this integrated into
Squid's source code, so please provide us feedback with any
suggestions.
Our https_port directive also follows, to serve as an example
configuration:
https_port 3443
cert=/etc/ssl/private/proxy.crt
key=/etc/ssl/private/proxy.key
options=NO_SSLv3,
No_Compression,
SINGLE_DH_USE,
SINGLE_ECDH_USE,
CIPHER_SERVER_PREFERENCE
dhparams=/etc/ssl/dhparam/dh2048.pem
eecdhcurve=prime256v1
cipher=ECDHE-ECDSA-CHACHA20-POLY1305:
ECDHE-RSA-CHACHA20-POLY1305:
DHE-RSA-CHACHA20-POLY1305:
EECDH+ECDSA+AESGCM:
EECDH+aRSA+AESGCM:
EDH+aRSA+AESGCM:
EECDH+ECDSA+SHA384:
EECDH+aRSA+SHA384:
EDH+aRSA+SHA384:
EECDH+ECDSA+SHA256:
EECDH+aRSA+SHA256:
EDH+aRSA+SHA256:
EECDH:EDH+aRSA:
!RC4:!aNULL:!eNULL:!LOW:!3DES:
!MD5:!EXP:!PSK:!SRP:!DSS
Best regards,
Paulo Matias
-------------- next part --------------
=== modified file 'doc/release-notes/release-4.sgml'
--- doc/release-notes/release-4.sgml 2015-03-28 11:12:46 +0000
+++ doc/release-notes/release-4.sgml 2015-05-20 12:28:18 +0000
@@ -133,6 +133,8 @@
<tag>https_port</tag>
<p>All <em>version=</em> <em>option=</em> values for SSLv2
configuration or disabling have been removed.
+ <p>New parameter <em>eecdhcurve</em> for specifying an
+ elliptic curve for ephemeral ECDH key exchange.
<p>Manual squid.conf update may be required on upgrade.
<tag>sslcrtd_children</tag>
=== modified file 'src/anyp/PortCfg.cc'
--- src/anyp/PortCfg.cc 2015-01-14 17:10:20 +0000
+++ src/anyp/PortCfg.cc 2015-05-19 14:46:04 +0000
@@ -53,6 +53,7 @@
capath(NULL),
crlfile(NULL),
dhfile(NULL),
+ eecdhcurve(NULL),
sslflags(NULL),
sslContextSessionId(NULL),
generateHostCertificates(false),
@@ -94,6 +95,7 @@
safe_free(capath);
safe_free(crlfile);
safe_free(dhfile);
+ safe_free(eecdhcurve);
safe_free(sslflags);
safe_free(sslContextSessionId);
#endif
@@ -139,6 +141,8 @@
b->crlfile = xstrdup(crlfile);
if (dhfile)
b->dhfile = xstrdup(dhfile);
+ if (eecdhcurve)
+ b->eecdhcurve = xstrdup(eecdhcurve);
if (sslflags)
b->sslflags = xstrdup(sslflags);
if (sslContextSessionId)
=== modified file 'src/anyp/PortCfg.h'
--- src/anyp/PortCfg.h 2015-01-13 07:25:36 +0000
+++ src/anyp/PortCfg.h 2015-05-19 14:46:04 +0000
@@ -78,6 +78,7 @@
char *capath;
char *crlfile;
char *dhfile;
+ char *eecdhcurve;
char *sslflags;
char *sslContextSessionId; ///< "session id context" for staticSslContext
bool generateHostCertificates; ///< dynamically make host cert for sslBump
=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc 2015-05-15 12:50:09 +0000
+++ src/cache_cf.cc 2015-05-19 14:46:04 +0000
@@ -3606,6 +3606,9 @@
} else if (strncmp(token, "dhparams=", 9) == 0) {
safe_free(s->dhfile);
s->dhfile = xstrdup(token + 9);
+ } else if (strncmp(token, "eecdhcurve=", 11) == 0) {
+ safe_free(s->eecdhcurve);
+ s->eecdhcurve = xstrdup(token + 11);
} else if (strncmp(token, "sslflags=", 9) == 0) {
safe_free(s->sslflags);
s->sslflags = xstrdup(token + 9);
@@ -3829,6 +3832,9 @@
if (s->dhfile)
storeAppendPrintf(e, " dhparams=%s", s->dhfile);
+ if (s->eecdhcurve)
+ storeAppendPrintf(e, " eecdhcurve=%s", s->eecdhcurve);
+
if (s->sslflags)
storeAppendPrintf(e, " sslflags=%s", s->sslflags);
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2015-05-15 12:50:09 +0000
+++ src/cf.data.pre 2015-05-20 12:23:53 +0000
@@ -2122,6 +2122,11 @@
Always create a new key when using
temporary/ephemeral DH key exchanges
+ SINGLE_ECDH_USE
+ Enable ephemeral ECDH key exchange.
+ The adopted curve should be specified
+ using the eecdhcurve option.
+
SSL_OP_NO_TICKET
Disable use of RFC5077 session tickets.
Some servers may have problems
@@ -2153,6 +2158,9 @@
dhparams= File containing DH parameters for temporary/ephemeral
DH key exchanges.
+ eecdhcurve= Elliptic Curve used for ephemeral ECDH. Supported curves
+ can be listed using "openssl ecparam -list_curves".
+
sslflags= Various flags modifying the use of SSL:
DELAYED_AUTH
Don't request client certificates
=== modified file 'src/ssl/support.cc'
--- src/ssl/support.cc 2015-05-08 11:18:30 +0000
+++ src/ssl/support.cc 2015-05-19 14:50:44 +0000
@@ -472,6 +472,11 @@
"NO_TICKET", SSL_OP_NO_TICKET
},
#endif
+#if SSL_OP_SINGLE_ECDH_USE
+ {
+ "SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE
+ },
+#endif
{
"", 0
},
@@ -824,11 +829,46 @@
}
static bool
+configureSslEECDH(SSL_CTX *sslContext, const char *curve)
+{
+ bool ok = true;
+#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
+#ifndef OPENSSL_NO_ECDH
+ int nid = OBJ_sn2nid(curve);
+ if (!nid)
+ return false;
+
+ EC_KEY *ecdh = EC_KEY_new_by_curve_name(nid);
+ if (ecdh == NULL)
+ return false;
+
+ ok = SSL_CTX_set_tmp_ecdh(sslContext, ecdh) != 0;
+ EC_KEY_free(ecdh);
+#endif
+#endif
+ return ok;
+}
+
+static void
+ssl_info_cb(const SSL *ssl, int where, int ret)
+{
+ (void)ret;
+#ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
+ if ((where & SSL_CB_HANDSHAKE_DONE) != 0) {
+ // disable renegotiation (CVE-2009-3555)
+ ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
+ }
+#endif
+}
+
+static bool
configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
{
int ssl_error;
SSL_CTX_set_options(sslContext, port.sslOptions);
+ SSL_CTX_set_info_callback(sslContext, ssl_info_cb);
+
if (port.sslContextSessionId)
SSL_CTX_set_session_id_context(sslContext, (const unsigned char *)port.sslContextSessionId, strlen(port.sslContextSessionId));
@@ -855,6 +895,15 @@
debugs(83, 9, "Setting RSA key generation callback.");
SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
+ if (port.eecdhcurve) {
+ debugs(83, 9, "Setting Ephemeral ECDH curve to " << port.eecdhcurve << ".");
+
+ if (!configureSslEECDH(sslContext, port.eecdhcurve)) {
+ ssl_error = ERR_get_error();
+ debugs(83, DBG_IMPORTANT, "WARNING: Unable to configure Ephemeral ECDH: " << ERR_error_string(ssl_error, NULL));
+ }
+ }
+
debugs(83, 9, "Setting CA certificate locations.");
const char *cafile = port.cafile ? port.cafile : port.clientca;
@@ -1155,6 +1204,8 @@
SSL_CTX_set_options(sslContext, Ssl::parse_options(options));
+ SSL_CTX_set_info_callback(sslContext, ssl_info_cb);
+
if (*cipher) {
debugs(83, 5, "Using chiper suite " << cipher << ".");
More information about the squid-users
mailing list