Bug 61081 - per-domain SNI (to override per-vhost SNI)
Summary: per-domain SNI (to override per-vhost SNI)
Status: NEW
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_ssl (show other bugs)
Version: 2.4.25
Hardware: All All
: P2 enhancement with 2 votes (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-05-09 14:32 UTC by felipe
Modified: 2018-08-29 00:24 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description felipe 2017-05-09 14:32:36 UTC
Currently there is no way to associate an SSL certificate with a specific FQDN unless that FQDN is the only one on its virtual host. We have longstanding user expectations of specific patterns of FQDN/vhost grouping, though, so we can’t switch to that without a great deal of pain for ourselves and our customers.

We could use Include and mimic the behavior, but that would increase the load time on machines that serve many thousands of vhosts.

The situation is aggravated by the fact that all other SSL-enabled services that we deploy--Exim, Dovecot, ProFTPd, and our own application--make it simple to associate an SSL certificate with a specific FQDN. So we’re having to maintain two separate SSL datastores and trying not to have our end users worry about the complexities of Apache’s model versus everyone else’s, but it doesn’t always work.

Has there been any discussion of a simple FQDN-to-certificate index in the config, as an alternative to vhost-based SNI?

e.g.:

-----------------
<NameBasedSNI>
    <Name example.com www.example.com>
        CertificateChainFile /path/to/certs/chain
        CertificateKeyFile /path/to/key
    </Name>
    <Name somealias.com www.somealias.com>
        CertificateChainFile /path/to/certs/chain
        CertificateKeyFile /path/to/key
    </Name>
    <Name mail.somealias.com>
        CertificateChainFile /path/to/certs/chain
        CertificateKeyFile /path/to/key
    </Name>
    <Name *.somealias.com>
        CertificateChainFile /path/to/certs/chain
        CertificateKeyFile /path/to/key
    </Name>
</NameBasedSNI>

… then there would just be the normal vhost configuration:

<VirtualHost 1.2.3.4:443>
    ServerName example.com
    ServerAlias www.example.com somealias.com www.somealias.com
    #...
</VirtualHost>
-----------------

This would allow applications like ours to treat Apache the same way as other services: there could just be a single datastore of certificates, indexed by domain, rather than having to maintain Apache’s as a “special exception”.

While this is just our own particular deployment, it’s also one that powers probably millions of sites. It also seems to me that decoupling the SNI from the delivered content would be a better design?

Thank you for your consideration!
Comment 1 Eric Covener 2017-05-09 15:06:46 UTC
(In reply to felipe from comment #0)
> Currently there is no way to associate an SSL certificate with a specific
> FQDN unless that FQDN is the only one on its virtual host.

Is this true? The code looks like it scans ServerAlias entries (ssl_util_vhost_matches) to use the SNI name to map to an SSL vhost config.
Comment 2 felipe 2017-05-09 15:11:52 UTC
(In reply to Eric Covener from comment #1)
> (In reply to felipe from comment #0)
> > Currently there is no way to associate an SSL certificate with a specific
> > FQDN unless that FQDN is the only one on its virtual host.
> 
> Is this true? The code looks like it scans ServerAlias entries
> (ssl_util_vhost_matches) to use the SNI name to map to an SSL vhost config.

This associates the certificate with the vhost, not with an individual FQDN. So all FQDNs on the vhost have to share a single certificate.

What I’m proposing is a means to decouple the vhost logic from SNI matching: if there’s a matching NameBasedSNI entry for the cert/key, then use that; otherwise, do business as usual.
Comment 3 Eric Covener 2017-05-09 15:24:21 UTC
(In reply to felipe from comment #2)
> (In reply to Eric Covener from comment #1)
> > (In reply to felipe from comment #0)
> > > Currently there is no way to associate an SSL certificate with a specific
> > > FQDN unless that FQDN is the only one on its virtual host.
> > 
> > Is this true? The code looks like it scans ServerAlias entries
> > (ssl_util_vhost_matches) to use the SNI name to map to an SSL vhost config.
> 
> This associates the certificate with the vhost, not with an individual FQDN.
> So all FQDNs on the vhost have to share a single certificate.
> 
> What I’m proposing is a means to decouple the vhost logic from SNI matching:
> if there’s a matching NameBasedSNI entry for the cert/key, then use that;
> otherwise, do business as usual.

I see, I think that is reasonable, but I would suggest avoiding new container/section construct for it.  In a proprietary SSL plugin, that uses
named certificates rather than paths, it was just repeated
"SSLSNIMap hostname label".

The interaction with current ssl-vhost-config selection by SNI would need to be sorted out too.  Documenting the status quo would be a good start!
Comment 4 felipe 2017-05-09 15:37:33 UTC
(In reply to Eric Covener from comment #3)
> 
> I see, I think that is reasonable, but I would suggest avoiding new
> container/section construct for it.  In a proprietary SSL plugin, that uses
> named certificates rather than paths, it was just repeated
> "SSLSNIMap hostname label".

However it seems most reasonably implemented in the config would be fine with me. :)

It seems like right before ssl_find_vhost() is where this would happen?

> 
> The interaction with current ssl-vhost-config selection by SNI would need to
> be sorted out too.  Documenting the status quo would be a good start!

I think just having a fallback would suffice?
Comment 5 felipe 2017-05-10 00:11:25 UTC
Incidentally, lighttpd’s SNI functionality is per-domain, not per-vhost:

$SERVER["socket"] == ":443" {
    ssl.engine  = "enable" 
    ssl.pemfile = "/etc/lighttpd/ssl/the-default-domain.com.pem" 
    $HTTP["host"] == "www.example.org" {
        ssl.pemfile = "/etc/lighttpd/www.example.org.pem" 
    }
    $HTTP["host"] == "mail.example.org" {
        ssl.pemfile = "/etc/lighttpd/mail.example.org.pem" 
    }
}
Comment 6 Adam Gardner 2018-08-29 00:24:44 UTC
I think a directive similar to IBM's SSLSNIMap would be ideal; I'm unsure whether it'd be preferable to have separate mapping directives for the certificate, key and chain files, or if you'd want one directive with multiple arguments. The latter would get extremely lengthy, so I'm leaning towards the former.