OCSP stapling issue with Nginx

My domain is: https://donald.pragmatika.net (but affects all my servers)

I ran this command:

bash /opt/testssl.sh/testssl.sh --openssl=/etc/nginx/openssl/bin/openssl https://donald.pragmatika.net:443

It produced this output:

First run

 Testing server preferences 

 Has server cipher order?     yes (OK) -- TLS 1.3 and below
 Negotiated protocol          TLSv1.3
 Negotiated cipher            TLS_AES_256_GCM_SHA384, 256 bit ECDH (P-256)
 Cipher order
    TLSv1.2:   ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-CHACHA20-POLY1305 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-SHA384 ECDHE-RSA-AES128-SHA256 
    TLSv1.3:   TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 TLS_AES_128_GCM_SHA256 


 Testing server defaults (Server Hello) 

 TLS extensions (standard)    "renegotiation info/#65281" "server name/#0" "EC point formats/#11" "next protocol/#13172" "supported versions/#43" "key share/#51"
                              "status request/#5" "max fragment length/#1" "application layer protocol negotiation/#16" "encrypt-then-mac/#22"
                              "extended master secret/#23"
 Session Ticket RFC 5077 hint no -- no lifetime advertised
 SSL Session ID support       yes
 Session Resumption           Tickets no, ID: yes
 TLS clock skew               Random values, no fingerprinting possible 
 Signature Algorithm          SHA256 with RSA
 Server key size              RSA 4096 bits
 Server key usage             Digital Signature, Key Encipherment
 Server extended key usage    TLS Web Server Authentication, TLS Web Client Authentication
 Serial / Fingerprints        04EC947430A3EEEB16EDD1AA236D14C2F34D / SHA1 1000702603AB4BDFD1C5A6210C48A947CC080A12
                              SHA256 FD3011B6F9431FE1ED82C5D4D4514ED747C902AAE2DE50B8D77BBA39CEA37586
 Common Name (CN)             donald.pragmatika.net 
 subjectAltName (SAN)         donald.pragmatika.net 
 Issuer                       Let's Encrypt Authority X3 (Let's Encrypt from US)
 Trust (hostname)             Ok via SAN (same w/o SNI)
 Chain of trust               Ok   
 EV cert (experimental)       no 
 ETS/"eTLS", visibility info  not present
 Certificate Validity (UTC)   89 >= 30 days (2020-04-12 17:18 --> 2020-07-11 17:18)
 # of certificates provided   2
 Certificate Revocation List  --
 OCSP URI                     http://ocsp.int-x3.letsencrypt.org
 OCSP stapling                not offered
 OCSP must staple extension   requires OCSP stapling (NOT ok)
 DNS CAA RR (experimental)    available - please check for match with "Issuer" above
                              issue=letsencrypt.org, issuewild=;
 Certificate Transparency     yes (certificate extension)

Note: OCSP not firing correctly.

 OCSP stapling                not offered
 OCSP must staple extension   requires OCSP stapling (NOT ok)

Second run

 Testing server defaults (Server Hello) 

 TLS extensions (standard)    "renegotiation info/#65281" "server name/#0" "EC point formats/#11" "status request/#5" "next protocol/#13172" "supported versions/#43"
                              "key share/#51" "max fragment length/#1" "application layer protocol negotiation/#16" "encrypt-then-mac/#22" "extended master secret/#23"
 Session Ticket RFC 5077 hint no -- no lifetime advertised
 SSL Session ID support       yes
 Session Resumption           Tickets no, ID: yes
 TLS clock skew               Random values, no fingerprinting possible 
 Signature Algorithm          SHA256 with RSA
 Server key size              RSA 4096 bits
 Server key usage             Digital Signature, Key Encipherment
 Server extended key usage    TLS Web Server Authentication, TLS Web Client Authentication
 Serial / Fingerprints        04EC947430A3EEEB16EDD1AA236D14C2F34D / SHA1 1000702603AB4BDFD1C5A6210C48A947CC080A12
                              SHA256 FD3011B6F9431FE1ED82C5D4D4514ED747C902AAE2DE50B8D77BBA39CEA37586
 Common Name (CN)             donald.pragmatika.net 
 subjectAltName (SAN)         donald.pragmatika.net 
 Issuer                       Let's Encrypt Authority X3 (Let's Encrypt from US)
 Trust (hostname)             Ok via SAN (same w/o SNI)
 Chain of trust               Ok   
 EV cert (experimental)       no 
 ETS/"eTLS", visibility info  not present
 Certificate Validity (UTC)   89 >= 30 days (2020-04-12 17:18 --> 2020-07-11 17:18)
 # of certificates provided   2
 Certificate Revocation List  --
 OCSP URI                     http://ocsp.int-x3.letsencrypt.org
 OCSP stapling                offered, not revoked
 OCSP must staple extension   supported
 DNS CAA RR (experimental)    available - please check for match with "Issuer" above
                              issue=letsencrypt.org, issuewild=;
 Certificate Transparency     yes (certificate extension)

Note: OCSP is firing correctly.

 OCSP stapling                offered, not revoked
 OCSP must staple extension   supported

My web server is (include version): Nginx 1.17.9

The operating system my web server runs on is (include version): Ubuntu 18.04.3 LTS

My hosting provider, if applicable, is: DigitalOcean

I can login to a root shell on my machine (yes or no, or I don’t know): Yes

I’m using a control panel to manage my site (no, or provide the name and version of the control panel): No

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you’re using Certbot): certbot 1.3.0

This is the command I use to (successfully) obtain a certificate:

sudo /opt/certbot/certbot-auto \
certonly \
--agree-tos \
--cert-name $heartbeat_fqdn \
--config-dir /etc/certbot/ \
--domains $heartbeat_fqdn \
--email $certbotemail \
--key-path /etc/certbot/live/$heartbeat_fqdn/ \
--must-staple \
--no-eff-email \
--rsa-key-size 4096 \
--server https://acme-v02.api.letsencrypt.org/directory \
--staple-ocsp \
--webroot \
--webroot-path /var/www/heartbeat/_well-known

Note: OCSP stapling and is set, along with ‘must staple’.

I have an Nginx server and I am aware this might be outside the LE remit, but I’m gradually pulling my hair out over this, so I would greatly appreciate some help in understanding why this is happening.

Overview

When Nginx is restarted and TLS is set up correctly, the first visit to the site - whether it’s testssl.sh or similar TLS checker - will report broken OCSP stapling. A subsequent test with no other activity taking place will report working OCSP stapling.

If a Firefox-based browser hits the site as the first visitor after an Nginx restart, a MOZILLA_PKIX_ERROR_REQUIRED_TLS_FEATURE_MISSING error is thrown - OCSP stapling not working. A page refresh resolves this, and subsequent page views work fine. I also tested Mac/Safari and that works first time.

Nginx has primary and secondary resolvers for DNS, both appear to be working, and there’s a 10 second timeout which happens after the error is thrown, so I can only think there’s some sort of OCSP snag that I’m hitting for the (un)lucky first customer that hits the site.

Any advice or feedback very welcome. Thank you in advance.

The only thing I can think of is that since your server has both IPv4 and IPv6 and verification can be via either, perhaps one of those is NOT working correctly.

As an aside, and since you seem to have taken the time to secure your site well, I would like to point out one small place for improvement:
image
Much like Cipher preference ordering, here you have missed an opportunity to reorder from highest to lowest.
In NGINX, that can be done with ssl_ecdh_curve.
My preference is:
ssl_ecdh_curve sect571r1:secp521r1:X448:sect409r1:secp384r1:sect283r1:prime256v1;

That’s just how Nginx works. If the worker process (I believe) doesn’t have an OCSP response cached, it doesn’t wait. It handles the connection without OCSP stapling, and fires off an OCSP request in the background.

The only web servers with reliable OCSP stapling implementations are, I think, Caddy and IIS.

Using OCSP stapling with anything else is unreliable or requires a lot of work, and you shouldn’t use must-staple.

(Nginx supports statically configuring OCSP responses to staple, so you could use an external daemon to manage them. But I don’t think anyone’s written one.)

(Certbot is working on one for Apache, though.)

3 Likes

Hi @petecooper

that’s expected.

My IIS has the same problem - new start of the test system, Firefox shows

MOZILLA_PKIX_ERROR_REQUIRED_TLS_FEATURE_MISSING

It works if only the application pool is restartet. But if that IIS website was shutdown, then I see the message.

The productive system (with a lot of customer subdomains and the “check-your-website”): There the problem is “too short”, so it’s not really a problem.

But the test system -> it happens. Hitting F5 is enough to fix it.

Thank you, Rudy – I appreciate you taking the time to poke around!

I’m using the Mozilla ‘Modern’ TLS setup at version 4.0 (since I have some issues with getting 5.0 working, but that’s for another time):

https://wiki.mozilla.org/Security/Archive/Server_Side_TLS_4.0#Modern_compatibility

…and this is how I roll:

mozilla_modern_40_tls_curves_json=$(curl 'https://statics.tls.security.mozilla.org/server-side-tls-conf-4.0.json' | jq .configurations.modern.tls_curves) \
&& mozilla_modern_40_tls_curves_nginx=$(echo $mozilla_modern_40_tls_curves_json | sed 's/ //g ; s/\"//g ; s/\[//g ; s/\]//g ; s/,/:/g') \
&& nginx_curves_old=$(sudo cat /etc/nginx/nginx.conf | grep ssl_ecdh_curve) \
&& sudo sed -i "s/ssl_ecdh_curve.*/ssl_ecdh_curve \'$mozilla_modern_40_tls_curves_nginx\';/g" /etc/nginx/nginx.conf \
&& echo -e 'Checking Nginx: '$mozilla_modern_40_tls_curves_nginx'...' \
&& sudo nginx -t \
&& sudo systemctl restart nginx

When I’ve got my head around text re-ordering, I will definitely heed your advice and change the curve order. Thank you!

Thank you, Matt. You’ve hit the nail on the head. Time for a re-think on my part.

Thank you, Juergen – exactly the issue I have, most of the time the sites are busy enough that it’s a tiny problem, but I am still keen to find a workable solution, or disable OCSP stapling if I cannot implement it sensibly.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.