I want to configure Caddy so that only tls1.2 is used and for the ciphers ECDHE-ECDSA-AES256-GCM-SHA384 and ECDHE-ECDSA-AES128-GCM-SHA256; the key_type is p256.
According to the observatory by Mozilla and the other scanners my server is still serving tls1.1 and tls1.2 and additionally to the above ciphers also ECDHE-ECDSA-AES256-SHA and ECDHE-ECDSA-AES128-SHA. Only the key_type directive is used.
After changing the Caddyfile, I deleted the /etc/ssl/caddy folder to get the new key and restarted Caddy. I’m using version Caddy 0.9.1 (+e8e5595 Sun Sep 18 15:41:37 UTC 2016) on Archlinux.
http2: TLSConfig.CipherSuites is missing HTTP/2-required TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Anyway, turning http2 off and using your Caddyfile, sslscan shows:
Version: 1.11.6
OpenSSL 1.0.2h 3 May 2016
OpenSSL version does not support SSLv2
SSLv2 ciphers will not be detected
Testing SSL server on port 443
TLS renegotiation:
Session renegotiation not supported
TLS Compression:
Compression disabled
Heartbleed:
TLS 1.2 not vulnerable to heartbleed
TLS 1.1 not vulnerable to heartbleed
TLS 1.0 not vulnerable to heartbleed
Supported Server Cipher(s):
Preferred TLSv1.2 256 bits ECDHE-ECDSA-AES256-GCM-SHA384 Curve P-256 DHE 256
Accepted TLSv1.2 128 bits ECDHE-ECDSA-AES128-GCM-SHA256 Curve P-256 DHE 256
Which is expected.
Do you know what you’re doing when you modify the cipher suites while running http2? There’s a stern warning about this in the docs:
Note: The HTTP/2 spec blacklists over 275 cipher suites for security reasons. Unless you know what you’re doing, it’s best to accept the default cipher suite settings.
TLS_ECDHE_RSA_WITH_AES128_GCM_SHA256 is missing, because the certificate is ECC instead of RSA, so ECDSA is used. That should be no problem.
According to the source code of config.go http2 blocks all but the 4 GCM ciphers:
// Note that, at time of writing, HTTP/2 blacklists 276 cipher suites,
// including all but four of the suites below (the four GCM suites).
// See https://http2.github.io/http2-spec/#BadCipherSuites
So in my case, only ECDHE-ECDSA-AES256-GCM-SHA384 and ECDHE-ECDSA-AES128-GCM-SHA256 should be used.
But why is Caddy still sending tls1.1 and those two ciphers with only SHA1? I need to get rid of these to get the modern compatibility ranking from Mozilla.
protocol: If min and max are the same, it need only be specified once. ciphers... If you list any, only the ones you specify will be allowed.
I think you still have to allow it for HTTP/2 to be configured properly, however. So I had to go look this up, and it says right in the HTTP/2 spec:
To avoid this problem causing TLS handshake failures, deployments of HTTP/2 that use TLS
1.2 MUST support TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE]
with the P-256 elliptic curve [FIPS186].
So I guess keep the RSA suite in there.
No idea, it doesn’t show that for me when I try it here.
I’m going to try to get a new Caddy release out this week – try that or build from source sooner and see if it was fixed in the interim? I can’t remember, we made a few little tweaks to TLS stuff recently.
Ok, so I tried the new 0.9.2 and the problem persisted, BUT I found the solution after deleting all other domains.
In addition to the domain above, I also had the following block in my Caddyfile (and another domain with corresponding subdomains but that shouldn’t be relevant):
After deleting this block, sslscan showed the correct values for mkoppmann.at, with only TLS1.2 being activated with the right ciphers. Copying the tls directive from the main domain to www subdomain resulted in both being served correctly.
So what’s the reason I’m apparently getting the default tls values from the www subdomain altough I’m directly visiting the main domain? And is it possible to write one single tls directive which is used by all domains or do I have to copy it into each block?
I found the following snippet in the docs but I guess that’s for multiple sites which share the exact same config:
For sites which share the same configuration, specify multiple addresses:
localhost:2020, https://site.com, http://mysite.com {
...
}
Thanks in advance.
Edit: The other domains actually do matter. I need to copy the tls directive into every block in the Caddyfile to get the right values.
// Go with the widest range of protocol versions
if config.MinVersion == 0 || cfg.ProtocolMinVersion < config.MinVersion {
config.MinVersion = cfg.ProtocolMinVersion
}
if cfg.ProtocolMaxVersion > config.MaxVersion {
config.MaxVersion = cfg.ProtocolMaxVersion
}
See, multiple sites are served on the same listener if they share a port. So we have to reduce multiple site configs down to a single TLS config. How to do that is not really obvious.
So a site with the default TLS settings will still allow TLS 1.1, and when combined with a different site that only allows TLS 1.2, the widest range of protocols is used, meaning TLS 1.1 and TLS 1.2 are both permitted. Which explains why you need to copy the TLS block to all the sites.
Hm, sorry about that. I chose to go with the widest range of protocols for compatibility reasons, but maybe we should invert the rule, so that it’s the narrowest range? What is more expected, and makes more sense?
The defaults in Caddy are already very secure so I would stick with the compatibility route. By choosing the narrowest range, one would just lose clients because they can’t connect anymore, just because one domain is more restricted.
The only thing is, that according to that list here there is almost no browser out there, that supports TLS1.1 but not 1.2.
Google Chrome from 2012.09 to 2013.10 is the only relevant client I guess. But that’s probably not the right thread to discuss this.
Would it not be possible to do something like this?