Hey willy,

One small comment. As of openssl v1.0.2 it actually supports loading multiple certificates with different chains. It requires calling SSL_CTX_add0_chain_cert (or SSL_CTX_add1_chain_cert, the exact difference can be found in the man page) instead of SSL_CTX_add_extra_chain_cert. I've actually hacked this in using a quick ad dirty method, but haven't gotten around to fixing it properly: https://github.com/haproxy/haproxy-1.5/compare/master...RobinGeuze:master

Besides that I agree with the idea of letting openssl do the actual cipher selection and such, since it keeps ssl specific logic from the haproxy code base, and openssl also does some specific checks that would need to be copied to haproxy (for example it checks whether the cipher fingerprint matches a bunch of safari versions and then disables ECDSA as an option since it was broken in those safari versions).

-Robin

On 8/25/2015 16:36, Willy Tarreau wrote:
Hi guys,

Yesterday Emeric and I brainstormed on this subject in the office. Emeric
brought on the table some cases which couldn't be reliably covered anymore,
and proposed a slightly different approach which finally convinced me.

I'll try to summarize here our long conversation and we'd like to get some
feedback on the various proposals.

A bit of background first.

1) it is currently possible to load multiple certs for the same domain in
    the config, and in this case, the first one loaded will be considered,
    regardless of its key type (RSA, DSA, ECDSA).

2) in crt-lists, it is possible to write filters which override the cert's CN
    and alt names. Similarly, these ones are considered in their declaration
    order so that the first matching one is used.

3) crt-lists support wildcards with exclusion. The cert registration works
    like this :

        a) the cert is declared :

             foo.pem *.mydomain.com !mail.mydomain.com

        b) the cert is loaded and an SSL_CTX is created.

        c) an entry is added into the wildcard tree at ".mydomain.com" with
           a reference to the SSL_CTX.

        d) another entry is added into the FQDN tree at "mail.mydomain.com"
           with a negation flag set (to reflect the "!" in the filter).

   Lookup method works like this :

        1) lookup for SNI name in FQDN tree, and skip entries with the
           negation flag. If found, return this SSL_CTX.

        2) lookup for the SNI's domain in the wildcard tree. If found without
           a negation on the FQDN, then return it. (note there's currently a
           small bug there but that's a different story and out of scope for
           this brainstorming).

        3) otherwise return default cert if not strict-sni.

4) currently, we have only one cert chain per SSL_CTX. OCSP Stapling
    applies to an SSL_CTX as well since it related to a single cert.

5) a number of cert-specific configuration items can be found in auxiliary
    files named based on the cert file's name, such as ".issuer", ".ocsp",
    ".sctl", maybe ".pwd" later, and all are loaded relative to a single
    SSL_CTX, whether it makes sense or not for the future. For example,
    OCSP entries are per-SSL_CTX while they should become per-certificate.


The latest proposal introduces some problems above when there's some
overlapping between certs, because each time a certificate is loaded, a
lookup in the tree will be performed to try to locate other instances of
the same name(s) and update the corresponding SSL_CTX with the new cert.
But if there are multiple instances, it doesn't work anymore.

Also even without this, another issue is that names may not match exactly.
For example, a hosting provider could be adding a new ECDSA cert for one
customer only while the original RSA cert covers multiple customers. This
already introduces a problem since the ECDSA cert would have to be added
to the same SSL_CTX as the first one, thus would be presented for all
other domains.

It's possible of course to try to detect such configurations, but if we're
realistic, they're going to be the most common ones, because new certs
with multiple names will problably not reflect obsolete domains just like
they may introduce new names. So it doesn't seem a good approach longterm-
wise.

Emeric's proposal consists in adopting a slightly different approach.

Since the first cause of the trouble relates to matching the correct
SSL_CTX when loading the second cert, and the second problem relates
to name matching differences between certs in the same SSL_CTX, there
are two important things to keep in mind :

   - certificates to be presented together must be loaded together
   - the SSL_CTX only matches a combination of names

Thus the idea would be that when a certificate is loaded (either on the
crt line or from the crt-list file), instead of loading only one cert
and trying to match it against another one, better load all possible
certs at once in the same SSL_CTX.

This means that the RSA/DSA/ECDSA cert names must be derived from the
original cert name. That's the first point to address for which we have
several proposals. One benefit is that it doesn't change anything at all
for existing configurations, and this is an important design aspect.

The second point is that with 3 different cert types, we have at worst
6 combinations of names, that's not huge, especially in a context where
not all certs will exist in multiple formats and where when certs are
finally provided with the two formats, the names will have had the time
to converge, so overall there shouldn't be too many differences.

The first point related to loading all certs at once comes with various
options and impacts for the administrator.

Among the options we have considered :
- automatically load ".pem.1", ".pem.2", ... etc when ".pem" is loaded,
     and ensure that they all have a different key type. I'm having a problem
     with this, because how do we decide when to stop loading them ? And if
     someone removes .1, should we load .2 ? What happens when .pem is an
     arbitrary symlink to ".pem.1" ?

   - detect that when ".pem" points to a directory, we automatically load
     all key types found in it (.rsa, .dsa, .ecdsa, etc). That sounds
     appealing but the "crt" bind keyword already supports loading all certs
     from a subdirectory so that introduces some kind of confusion. Or we
     should decide that only if the name ends in ".pem" AND is a directory
     THEN we treat is this way. I don't find this cool to have such an
     exception to deal with, especially for people who have to automatically
     process config files. But there's still definitely something to do there.

   - detect that when the designated ".pem" doesn't exist, then we
     automatically try to load the available certs with names .pem.rsa,
     .pem.dsa, .pem.ecdsa. It additionally allows to switch back to a single
     format by simply creating a symlink from .pem to the cert of choice.

   - other options ?

I'd confess that at the moment this third model gets my preference, but it's
important to get feedback from people who use a lot of certs so that they can
suggest what trouble they may face with these approaches or what they like.

Of course in any case, the .issuer, .ocsp, .whatever would be provided as
extensions to the *real* cert's name.

The second point related to conflicting names can be addressed in two steps.
The first step consists in rejecting mismatching names. The second step
consists in creating a distinct SSL_CTX per name combination. Thus up to 3
for 2 cert types (names for cert1 only, common names, names for cert2 only),
or up to 6 for 3 cert types. Even if we don't implement it immediately, it's
important to have this in mind so that we reserve room in certificates storage
and not in SSL_CTX storage for whatever relates to the certificate.

It would probably lead to a 3-level architecture :

     Names  -----> SSL_CTX -----> certificates

Note that this is already what we have except that there's a 1:1 relation
on each arrow and that most of the cert-specific storage is put in the
SSL_CTX instead.

Thanks for reading till this point, and for any feedback, idea, criticism
you may have. Don't be shy.

Willy



Reply via email to