Caddy: Multiple certificate support (e.g. ECDSA & RSA)

Created on 13 Apr 2017  Â·  27Comments  Â·  Source: caddyserver/caddy

Like e.g. NGINX supports it

feature request help wanted

Most helpful comment

Attention @lenovouser @neilstuartcraig @giuem @may573 and others: This was a lot of work, but it's implemented in 6ca5828. Please try it out! Release candidates will be cut very shortly!!

All 27 comments

I'm not sure how this works (or should work with Caddy). Can you or someone elaborate?

I think this is for the tls cert key manual SSL, so that you can specify multiple versions of a cert, signed with a different key, i.e. an ECDSA key or an RSA key.

We can already specify multiple cert/key pairs:

You can use this directive multiple times to specify multiple certificate and key pairs.
https://caddyserver.com/docs/tls

e.g.

tls example.com.rsa.crt example.com.rsa.key
tls example.com.ecdsa.crt example.com.ecdsa.key

@lenovouser does that answer your issue? Seems to me like Caddy can already do this.

@francislavoie yep, you can specify this - but it always uses only the last directive instead of deciding between rsa and ecdsa

Okay, what determines which one to use?

It's determined by client support (based on the signature_algorithms extension in the handshake: ​ietf.org/rfc5246#signature_algorithms)

Also, some notes taken from the NGINX issue:

  • Only OpenSSL 1.0.2+ supports separate chains for different certificates. With older versions, things will only work properly if chains are exactly the same for all certificates used (or there are no chains at all).
  • OCSP stapling won't work properly with multiple certificates with OpenSSL versions before 1.0.1d+, 1.0.0k and 0.9.8y+. This is due to a bug in OpenSSL fixed in the versions specified.

Just found out Apache supports this too

Just had another thought - in case #1576 will be implemented and this here too, you should keep an eye on that the correct *.sct's get taken for the correct certificate in case multiple are specified. The NGINX extension also took care of that like this:

ssl_ct on;

ssl_certificate /path/to/rsa.pem;
ssl_certificate_key /path/to/rsa.key;
ssl_ct_static_scts /path/to/rsa/scts;

ssl_certificate /path/to/ecdsa.pem;
ssl_certificate_key /path/to/ecdsa.key;
ssl_ct_static_scts /path/to/ecdsa/scts;

Hi all
FWIW i'd love to see this feature too (i found this ticket because i was going to request the same feature). My usage would be that i'd server pref EC ciphersuites but support RSA's for the minority of older clients which don't (and never will, e.g. XP) support EC.

It would be awesome if Caddy could create/manage both an EC and an RSA LetsEncypt cert - i'd see that as being pretty essential as part of this.

Very happy to help with any testing/nginx-based input (i use EC & RSA concurrently in nginx right now).

One final note, i don't think you need to have different session secret(s) for EC and RSA - unless that's something specific to Caddy and/or Go.

Cheers!

@neilstuartcraig I'll look into this; I'm definitely interested in Caddy using ECC over RSA. I am hoping we could just switch over to ECC without having to manage certs with obsolete crypto. I think having to manage both is just temporary and am not yet sure how complex this will be. Does someone want to throw together a proof of concept?

@mholt - I'm probably missing something here (apologies if so) but Caddy already works for ECC. Specifying key_type as e.g. p256 with an LE cert results in that cert being ECC. This is great and works really well, i use it currently in a personal project i'm developing.

Being able to use both is currently mandatory for our audience demographics, we have anything from about 0.5% up to ~17% (i've checked this several times) of our audience who use clients which can't handle ECC. This variation is chiefly down to geography, for example, many of our users in Africa and also parts of Asia require RSA-based certs. This means that we absolutely must support at least RSA but we'd love to pref ECC above it in our server pref lists so that the majority of users on modern clients can reap the benefits.

NGINX handles this really nicely so the same sort of operational model would be great - selecting the appropriate cert based on the client hello vs the server ciphersuite pref list. FWIW, I believe NGINX essentially hands off this whole procedure to OpenSSL, not sure if that would/wouldn't be the same for Go/Caddy but from memory, OpenSSL 1.01f+ handle it properly.

I have literally never written a line of Go so it'd take me an age to produce anything but i'd be more than happy to help in any other way.

Cheers

@neilstuartcraig I need to see if the underlying lego library would support this; we'd request a second cert using an already-obtained authz, probably. But I don't know how this affects rate limits with Let's Encrypt and such, for the second issuance.

@mholt - Yep, for sure. Do let me know if i can do anything useful (research, contacting people, docs, testing etc.). Really appreciate you spending time looking into this. Cheers

The LE folks say that getting two of the same certificate (but of a different key type) still use two queries against the rate limit. Is it worth implementing this feature that is mainly useful only during this transitionary period to ECC that adds complexity and doubles the rate limit usage?

My opinion would be that it's worth it for at least some use cases. As i mentioned previously, some of our audiences have ~17% of folk who can't do EC - so for them we need RSA, but it seems a shame to "punish" the majority, 83%, of that demographic (not to mention other geographies who are ~0.5% who can't do EC) with ~7x slower TLS handshakes.

If the code complexity in Caddy is sufficiently high, perhaps it makes sense to ask Caddy users to manually manage their certs but if it's not so bad, it'd be a particularly nice feature (IMO). Of course, since Caddy supports TLS session tickets, handshake time is only a problem for first-time (per ticket secret lifetime) visitors - that too will obviously vary massively by user-base. FWIW, we're currently rotating TLS session secrets ~every 24h with a primary and secondary, thus a maximum session lifetime of ~48h - since we want to limit the scope of a compromised session secret.

If number of LE API queries is the major issue, i think if it's clearly documented that EC + RSA means 2x API queries, it's a conscious choice for the user which puts the decision in their hands.

Does that help? Apologies if i'm rambling nonsense :-)

@mholt Your point about the rate limit is valid, even though I think it should be no problem if you make it opt-in (only if it is configured for dual certificate support) because the admin then chooses to do so.

Also it could at least be implemented as a config file option for non-LE certificates if is too complex for LE and / or rate limiting.

Okay. Well, we can give it a go, but I have other things on my priority list right now (API, proxy rewrite, telemetry, updates to the dev portal, etc...) so if somebody would like to take a stab at it, let us know!

It's a nice feature. Currently I still use Nginx mainly because of this.

In Nginx, there is a key called ssl_ciphers that can specify the enabled ciphers.

To use ECDSA + RSA key, I set it to EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;

Here is SSL Server Test, you can see the server choose certificate correctly.

I hope this is helpful

Any update on this?

Nice! That's great, thanks for doing this. It'll be a great feature

On Thu, 10 Jan 2019, 11:00 Aaron, notifications@github.com wrote:

@lenovouser https://github.com/lenovouser @neilstuartcraig
https://github.com/neilstuartcraig @giuem https://github.com/giuem

Today I put up a job ad on reddit with a $1,000 reward for creating a pull
request which implements this feature.

I found at least one developer so far who is interested in working on
this. I'll keep you guys posted with their progress.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/mholt/caddy/issues/1575#issuecomment-453056066, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AATi14w-vzy-TrhBhOAQpRtXiHV1NCpTks5vBx06gaJpZM4M8q0U
.

@whalehub just wondering if there was ever any progress with that ad you put out?

Is there any update for this requirement?

This can be supported in Caddy 2 after Go 1.14 is released. But someone will have to propose and implement it.

Great, looking forward to it will come soon.

@mholt Just curious, what feature is planned for Go 1.14 that makes this possible?

@whalehub Presumably:

When multiple certificate chains are provided through the Config.Certificates field, the first one compatible with the peer is now automatically selected. This allows for example providing an ECDSA and an RSA certificate, and letting the package automatically select the best one.

Yep, although we don't use Certificates, so technically it's this one:

The new (ClientHelloInfo).SupportsCertificate and (CertificateRequestInfo).SupportsCertificate methods expose whether a peer supports a certain certificate.

Ooo and unrelated, but... it looks like this:

Config.Certificates and Config.GetCertificate can now both be nil if Config.GetConfigForClient is set. If the callbacks return neither certificates nor an error, the unrecognized_name is now sent.

Will finally fix https://github.com/caddyserver/caddy/pull/2404.

Attention @lenovouser @neilstuartcraig @giuem @may573 and others: This was a lot of work, but it's implemented in 6ca5828. Please try it out! Release candidates will be cut very shortly!!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aeroxy picture aeroxy  Â·  3Comments

dafanasiev picture dafanasiev  Â·  3Comments

muhammadmuzzammil1998 picture muhammadmuzzammil1998  Â·  3Comments

jgsqware picture jgsqware  Â·  3Comments

mschneider82 picture mschneider82  Â·  3Comments