You can run multiple name-based virtual hosts on your web server on a single IP using traditional X.509 certificates as long as the certificate you offer contains the proper entries in the SubjectAltName extension field. I started down this path thanks to CA Cert's vhost task force (their "Way 3"). The SubjectAltName extension is defined in RFC 3280, section 188.8.131.52.
Generating a certificate request with a SubjectAltName
Please see the CA Cert vhost task force's suggestion.
Signing a certificate to include a SubjectAltName
These notes assume that you are running your own Certificate Authority, and trying to embed multiple names in the certificate. They assume you're using openssl ca to manage your Certificate Authority.
Unfortunately, even given an openssl-generated certreq which includes SubjectAltName records in it, openssl ca doesn't automatically include the SubjectAltName records in the final certificate without some effort.
As a baseline, you need make sure that you've got the x509_extensions tag in yer CA's openssl.cnf configuration (not the certreq openssl.cnf). That tag should point to the name of another stanza in the same config file:
x509_extensions = server_cert_extensions
And that target stanza (we're still in the CA's openssl.cnf) should probably contain at least the following lines in it if you're issuing certificates for servers:
[ server_cert_extensions ] basicConstraints = CA:FALSE nsCertType = server subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always issuerAltName = issuer:copy
Now, depending on your situation you have two ways to adapt the above configuration to get the SubjectAltName field into your generated certificates:
- If you receive certificate requests which have embedded SubjectAltName extensions in them, (and you verify those extensions before you even think about signing them, naturally), then you can simply include the copy_extensions directive set to copy in the same stanza where you set x509_extensions (you may wish to read the WARNINGS section of the ca documentation if you're unclear on the risks here). So that would look like:
x509_extensions = server_cert_extensions copy_extensions = copyNow you can sign the certificates as you had before, and the extensions supplied by the certificate requests (with the exceptions of the ones you've explicitly overridden in the server_cert_extensions stanza) will be included in the new certs.
- Alternately, if your incoming certificate requests do not contain the correct SubjectAltName extensions, or tend to contain certificate extensions so untrustworthy that you'd rather ignore them, you can reference to an environment variable that will contain the SubjectAltName you plan on using in the server_cert_extensions stanza directly. Including the other directives listed above, that stanza would look like:
[ server_cert_extensions ] basicConstraints = CA:FALSE nsCertType = server subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always issuerAltName = issuer:copy subjectAltName = $ENV::SUBJECTALTNAMERAWthen, instead of signing with
openssl ca foo baryou'd sign with:
SUBJECTALTNAMERAW='DNS:a.b.c, DNS:d.b.c' openssl ca foo bar
I think this is right, but i'd be happy to hear comments/suggestions for improvement. Thanks to Terry McGonigal for pointing out copy_extensions to me!