This week I managed to finally migrate my personal website to SSL, and on top of that migrate the SMTP/IMAP services to certificates signed by “proper” a CA (instead of my own). This however was more complex than I thought…
I first wanted to do this when Let’s Encrypt became available, but the way it works - with short term certificates with automated renewal put me off at first. The certbot tool needs to make semi-arbitrary outgoing requests to renew the certificates, and on public machines I have a locked-down outgoing traffic policy. So I gave up, temporarily…
I later found out that at least for now (for the current protocol),
certbot only needs to talk to a certain API endpoint, and after some
more research, I realized that the
http-01 protocol is very
straight-forward, only needing to allow some specific plain http URLs.
Issue 1: allowing outgoing access to a given API endpoint,
somewhat restricted. I solved this by using a proxy, forcing
to go through it via env vars, learning about
systemctl edit on the
way, and from the proxy, only allowing that hostname. Quite weak, but
at least not “open policy”.
Issue 2: due to how
http-01 works, it requires to leave some
specific paths under http, which means you can’t have (in Apache) a
“redirect everything to https” config. While fixing this I learned
mod_macro, which is quite interesting (and doesn’t need an
The only remaining problem is that you can’t renew automatically
certificates for non-externally accessible systems; the
also need changing externally-visible state, so more or less the
Issue 3: For internal websites, still need a solution if own CA (self-signed, needs certificates added to clients) is not acceptable.
How did it go?
It seems that using SSL is more than
SSLEngine on. I learned in this
exercise about quite a few things.
DNS Certification Authority Authorization is pretty
nice, and although it’s not a strong guarantee (against malicious
CAs), it gives some more signals that proper clients could check (“For
this domain, only this CA is expected to sign certificates”); also,
trivial to configure, with the caveat that one would need
well for end-to-end checks.
I was completely unaware of OCSP Stapling, and yay, seems like a good solution to actually verifying that the certs were not revoked. However… there are many issues with it:
- there needs to be proper configuration on the webserver to not cause more problems than without; Apache at least, needs increasing the cache lifetime, disable sending error responses (for transient CA issues), etc.
- but even more, it requires the web server user to be able to make “random” outgoing requests, which IMHO is a big no-no
- even the command line tools (i.e.
openssl ocsp) are somewhat deficient: no proxy support (while
s_clientcan use one)
So the proper way to do this seems to be a separate piece of software, isolated from the webserver, that does proper/eager refresh of certificates while handling errors well.
Issue 4: No OCSP until I find a good way to do it.
HSTS, server-side and preloading
HTTP Strict Transport Security represent a commitment to encryption: once published with recommended lifetime, browsers will remember that the website shouldn’t be accessed over plain http, so you can’t rollback.
Preloading HSTS is even stronger, and so far I haven’t done it. Seems worthwhile, but I’ll wait another week or so ☺ It’s easily doable online.
Something I didn’t know before is that the servers are supposed to serve the entire chain; I thought, naïvely, that just the server is enough, since the browsers will have the root-root CA, but the intermediaries seem to be problematic.
So, one needs to properly serve the full chain (Let’s Encrypt makes this trivial, by the way), and also monitor that it is so.
Ciphers and SSL protocols
OpenSSL disabled SSLv2 in recent builds, but at least Debian stable still has SSLv3+ enabled and Apache does not disable it, so if you put your shiny new website through a SSL checker you get many issues (related strictly to ciphers).
I spent a bit of time researching and getting to the conclusion that:
- every reasonable client (for my small webserver) supports TLSv1.1+, so disabling SSLv3/TLSv1.0 solved a bunch of issues
- however, even for TLSv1.1+, a number of ciphers are not recommended by US standards, but going into explicit cipher disable is a pain because I don’t see a way to make it “cheap” (without needing manual maintenance); so there’s that, my website is not HIPAA compliant due to Camellia cipher.
Issue 5: Weak default configs
Issue 6: Getting perfect ciphers not easy.
However, while not perfect, getting a proper config once you did the research is pretty trivial in terms of configuration.
My apache config. Feedback welcome:
SSLProtocol all -SSLv3 -TLSv1
And similarly for dovecot:
ssl_cipher_list = HIGH:!aNULL
ssl_protocols = !SSLv3 !TLSv1
ssl_prefer_server_ciphers = yes
ssl_dh_parameters_length = 4096
The last line there - the
dh_params - I found via nmap, as my
previous config has it do 1024, which is weaker than the key,
defeating the purpose of a long key. Which leads to the next point:
It seems that DH parameters can be an issue, in the sense that way too many sites/people reuse the same params. Dovecot (in Debian) generates its own, but Apache (AFAIK) not, and needs explicit configuration added to use your own.
Issue 7: Investigate DH parameters for all software (postfix, dovecot, apache, ssh); see instructions.
A number interesting tools:
- Online resources to analyse https config: e.g. SSL labs, and htbridge; both give very detailed information.
- CAA checker (but this is trivial).
- nmap ciphers report:
nmap --script ssl-enum-ciphers, and very useful, although I don’t think this works for
- Cert Spotter from SSLMate. This
seems to be useful as a complement to
CAAbeing the policy, and Cert Spotter the monitoring for said policy), but it goes beyond it (key sizes, etc.); for the expiration part, I think nagios/icinga is easier if you already have it setup (
check_httphas options for lifetime checks).
- Certificate chain checker; trivial, but a useful extra check that the configuration is right.
Ah, the good old days of plain http. SSL seems to add a lot of complexity; I’m not sure how much is needed and how much could actually be removed by smarter software. But, not too bad, a few evenings of study is enough to get a start; probably the bigger cost is in the ongoing maintenance and keeping up with the changes.
Still, a number of unresolved issues. I think the next goal will be to find a way to properly do OCSP stapling.