mozilla/server-side-tls

switch to stateless session resumption for nginx TLSv1.3 only configuration

thestinger opened this issue · 2 comments

TLSv1.3 doesn't have session IDs or session tickets as their own features but rather only a generic session resumption system resembling tickets. Setting ssl_session_tickets off switches OpenSSL to using stateful TLSv1.3 resumption instead of stateless resumption. TLSv1.3 supports ECDHE session resumption and OpenSSL doesn't allow disabling it so it's always enabling no matter how people build it or configure it with another configuration file. That means it ALWAYS provides forward secrecy for resumed sessions for clients supporting it. In practice, no clients support only PSK without PSK + ECDHE resumption. Perhaps some weird embedded device. It would make a lot of sense to stop forcing stateful session caching for the TLSv1.3 only configuration.

The current approach of making a 10m shared memory region and using 1 day expiry is problematic because nginx will only purge 1 non-expired session in an attempt to free up room for a new session. However, the session state can vary in size and it's not uncommon to see errors logged (look in your error log) from this failing to free up room. If you have more than 40k sessions per 24h then your session cache is getting filled and you start seeing these errors. See https://trac.nginx.org/nginx/ticket/621 for details. You're making this mistake:

with configurations assuming nginx will silently throw away old sessions if there will be not enough memory in the shared memory zone

Also worth noting: for TLSv1.2, stateful resumption doesn't resolve the forward secrecy issues from tickets not being automatically rotated. nginx does not actively purge expired sessions from the cache, so they sit there indefinitely until churn pushes them out. The best solution is using ssl_session_ticket_key and doing your own rotation with a script but unfortunately that's beyond what the configuration generator can reasonably tell people to do. It's also easy for people to screw this up. They could have the rotation break or could end up doing their own approach not guaranteeing the files contain proper random keys at all times by not doing the rotation atomically, etc. I don't think nginx will be changing this because TLSv1.3 largely obsoletes the need to do it unless you need to synchronize across servers.

These 2 lines should be removed for the TLSv1.3 only configuration:

    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

Also see openssl/openssl#13918 about it not being possible to disable ECDHE PSK session resumption with OpenSSL. The client would need to not support ECDHE PSK resumption, i.e. not a web browser but rather some weird embedded client, and I don't think people need to worry about that. nginx does rotate the tickets when configuration is reloaded so at minimum it gets rotated when people reload the configuration for any reason, which is quite frequent if you're doing OCSP stapling with an external cache to work around the built-in stapling not working reliably for multiple reasons (actually, will file another issue about something related to that).

Also worth noting: for TLSv1.2, stateful resumption doesn't resolve the forward secrecy issues from tickets not being automatically rotated. nginx does not actively purge expired sessions from the cache, so they sit there indefinitely until churn pushes them out.

As from #284, this seems to be fixed in NGINX 1.23.2.