Some notes for implementing TLS/SSL on the server with OpenSSL:
Notes
- Users will upload a certificate/private key for each domain name (we don't yet support wildcard domains). We expect the certificates in PEM format, concatenated into a single file and in the appropriate order. We can upload via AI1 (or AI2 if we implement an upload feature).
- We can probably obtain the domain name from the certificate itself, but if not, we need the user to specify it.
- The upload gets handled by Cryptosaur, which parses and stores the certificate chain, indexed by domain name (subject). If a second cert is uploaded with the same domain name, we replace a previous one.
- We probably need a way to delete a certificate.
- Arc.service definitions should accept an additional parameter for
http
protocol. The parameter istls
, which can have one of three values:none
(only http),optional
(allow http or https),required
(force https). We might also need atlsPort
parameter in case we want to specify a different port. Foroptional
andrequired
we log an error if we don't have a certificate for that domain (once at startup). - Hyperion will ask Esper to listen for SSL connections (only once per port). Esper will then use Server Name Indication to figure out which domain is being requested. It will then ask Cryptosaur for the appropriate certificates and return those to the client. [And presumable Esper will cache them for some period of time (hours to days). TBD if we ever invalidate the cache.]
Links and Info
- http://serverfault.com/questions/9708/what-is-a-pem-file-and-how-does-it-differ-from-other-openssl-generated-key-file
- https://zakird.com/2013/10/13/certificate-parsing-with-openssl
- https://www.digicert.com/ssl-support/pem-ssl-creation.htm
- http://stackoverflow.com/questions/5113333/how-to-implement-server-name-indication-sni
- https://en.wikipedia.org/wiki/Server_Name_Indication
- http://stackoverflow.com/questions/33777302/is-openssl-thread-safe
- https://gist.github.com/MartinMReed/6393150
- http://stackoverflow.com/questions/20065304/what-is-the-differences-between-begin-rsa-private-key-and-begin-private-key
- https://wiki.openssl.org/index.php/Simple_TLS_Server
- http://stackoverflow.com/questions/256405/programmatically-create-x509-certificate-using-openssl
- https://www.trustworthyinternet.org/ssl-pulse/
- https://sslmate.com/: $150 per year for a wildcard certificate or $16 per year for a single domain.
Progress
2017-04-24
Fixed bugs with TLS connections; now works properly, though we of course get a warning about a self-signed certificate.
2017-03-13
Implemented certificate cache on Esper. Connection implemented with SSL certificates, but there's a bug which causes us to lose the connection.
We still need to implement loading certificates from Cryptosaur. This should be done at start up time.
2017-03-11
Implemented the Esper SSL session object and the Hyperion code to start an Esper listener on 443.
But I ran into a minor roadblock. The wrappers on OpenSSL assume a single SSL CTX, which spawns one SSL object per connection. But it turns out that Server Name Indication requires one SSL CTX per domain/certificate.
Esper is going to cache certificates per domain anyway, so we need to additionally cache an SSL CTX object. Esper should have a default SSL CTX, which has a callback for SNI. In the callback, we use the server name to lookup the proper SSL CTX. Then we switch the given SSL to the appropriate SSL CTX.
We need to change CSSLAsyncEngine to take an SSL CTX as a parameter (which can default to the global SSL CTX).
2017-02-26
Implemented Cryptosaur.setCertificate and AI1 upload. Now we can upload certificates and store them in Arc.certificates.
2017-02-19
Worked on wrappers for OpenSSL certificates and certificate stacks. We can load certificates from .PEM files.
We cannot, however, combine certificates and private keys into a single .PEM file. We need to add code that separately loads pieces of a single file into different places (a certificate stack and a private key object).
After that, we should be able to implement the Cryptosaur command to upload certificates. Next we should implement an upload command in AI1.