[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