First things first: if you are reading pages on this website, your connection will be secure because my web server is configured to only use HTTPS. To secure this connection, certificates are used. These certificates prove that your browser is actually talking to this site and not another site pretending to be vlent.nl.
Certificates can become invalid. One reason is that they expire: when you get a certificate from a certification authority, the certificate has a start and end date. For example, my current certificate is valid from April 10, 2014 and valid until April 10 2015. Outside these dates, clients (like your browser) should not accept this certificate.
Another way a certificate can become invalid is when it is revoked. This means that your client should no longer trust the certificate even though it may not be expired yet. One reason to revoke a certificate is when (you believe) the private key associated with the certificate is compromised. And that is exactly what could have happened due to the Heartbleed bug.
Revoked certificates are listed in so called certificate revocation lists. A more efficient alternative is the Online Certificate Status Protocol (OCSP). How the latter basically works is that the client asks the certificate authority (CA) that issued the certificate, whether the received certificate is still valid.
The downside of OCSP is that the client must contact the CA to discover whether the certificate is valid. This both creates a privacy issue (the CA knows which IPs were interested in a certain certificate), and a scaling issue: a CA might have to respond to a large number of requests when a site using ‘their’ certificate is for instance a high traffic web site.
OCSP stapling resolves this problem by having the certificate holder itself query the OCSP server of the CA at regular intervals. The response from the CA, which is signed and time stamped, is then added (“stapled”) to the response to the client visiting the web site.
So for example, when your browser connects to www.vlent.nl, my web server does not only return the usual certificate information, but the OCSP response is also included. This saves your browser a round trip to my CA.
Originally I had included the OCSP stapling mainly to tick another box
on
Qualys SSL Labs test report
without really understanding how it worked. To accomplish this, I used
the
ssl_stapling_file
directive
in my Nginx setup:
ssl_stapling on;
ssl_stapling_file path/to/file_with_ocsp_response;
This—in itself—is not a problem. However, what I did not realise was that the file with the OCSP response needed to be updated frequently. Since I did not do that, the result was something like this:
$ openssl s_client -connect www.vlent.nl:443 -tls1 -tlsextdebug -status
...
OCSP response:
======================================
OCSP Response Data:
...
Produced At: Oct 9 14:31:12 2013 GMT
...
Cert Status: good
This Update: Oct 9 14:31:12 2013 GMT
Next Update: Oct 11 14:31:12 2013 GMT
Although I ran the command last week (April 2014), the OCSP response data was still only valid until October 11th, 2013. Basically the OCSP stapling I used was just a waste of bits since it had only been valid for two days and clients still had to query the OCSP server themselves.
Luckily, there is an easy solution: have Nginx itself handle the OCSP stapling, for example with this configuration:
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/cert_chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
When I now check the response, I get:
$ openssl s_client -connect www.vlent.nl:443 -tls1 -tlsextdebug -status
OCSP response:
======================================
OCSP Response Data:
...
Produced At: Apr 19 07:33:29 2014 GMT
...
Cert Status: good
This Update: Apr 19 07:33:29 2014 GMT
Next Update: Apr 21 07:33:29 2014 GMT
Note that the OCSP response is valid while I last updated the Nginx configuration a week ago and have not touched it since.
When you have updated your configuration and restarted Nginx, you may
not get an OCSP response when you want to test. Instead, the result of
the openssl
command might contain this line instead of the OCSP
response data block:
OCSP response: no response sent
In that case, don’t immediately tweak your configuration. Just try again first.
And finally this: not all clients check whether a certificate is revoked or not. For instance in Chrome the online revocation check is disabled by default. But that is a completely different side of this story. There’s only so much a humble web server can do.
]]>While I could access Whiskers via https://whiskers.example.com, references in the HTML to the favicon and the CSS were to http://whiskers.example.com/static/… And that either generates a warning about unsafe content or the browser might decide to not load the assets at all. And especially the missing CSS was severely impacting the usability.
First I tried to solve this in Whiskers itself. But I soon discovered
that the master.pt
template in Whiskers contains several calls to
static_url,
for instance:
<link rel="stylesheet" href="${request.static_url('whiskers:static/css/bootstrap.css')}" ... />
<link rel="stylesheet" href="${request.static_url('whiskers:static/whiskers.css')}" ... />
And those resolved to http://whiskers.example.com/static/… so I had to convince Whiskers (or actually Pyramid) that we were using SSL. As a result my next attempts involved changing the Apache configuration. But after trying several options I could not get it working (possibly also due to an older version of Apache).
So I left the configuration unchanged:
<VirtualHost <ip>:443>
... basic stuff about the server name, logs and SSL certificates ...
RewriteEngine on
ProxyPreserveHost on
# We use a custom CSS file.
Alias /static/whiskers.css /var/www/whiskers/static/whiskers.css
RewriteRule ^/static/whiskers.css - [L]
RewriteRule ^(.*) http://127.0.0.1:6543$1 [P]
<Location />
AuthName "Whiskers"
AuthType Basic
AuthUserFile /path/to/htpasswd
require user spam eggs ham
</Location>
<Location /buildouts/add>
Satisfy Any
</Location>
</VirtualHost>
After stumbling on a link to
the reverse proxy section of the Waitress documentation
I decided to try a different approach. My production.ini
was
basically a copy from the
example on GitHub
and it contained this section:
[server:main]
use = egg:Paste#http
host = 0.0.0.0
port = 6543
I installed Waitress in my virtualenv and replaced the above section with this:
[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = 6543
url_scheme = https
And now the CSS is properly loaded!
I don’t know if there are easier/better ways to solve this, but this works fine for us.
]]>