[PATCH 01 of 11] SSL: disabled saving tickets to session cache
Sergey Kandaurov
pluknet at nginx.com
Thu Sep 29 15:09:15 UTC 2022
> On 28 Sep 2022, at 00:14, Maxim Dounin <mdounin at mdounin.ru> wrote:
>
> Hello!
>
> On Mon, Sep 26, 2022 at 02:11:17PM +0400, Sergey Kandaurov wrote:
>
>>> On 17 Sep 2022, at 00:58, Maxim Dounin <mdounin at mdounin.ru> wrote:
>>>
>>> On Thu, Sep 15, 2022 at 09:36:31AM +0400, Sergey Kandaurov wrote:
>>>
>>>>> On 26 Aug 2022, at 07:01, Maxim Dounin <mdounin at mdounin.ru> wrote:
>>>>>
>>>>> # HG changeset patch
>>>>> # User Maxim Dounin <mdounin at mdounin.ru>
>>>>> # Date 1661481945 -10800
>>>>> # Fri Aug 26 05:45:45 2022 +0300
>>>>> # Node ID 2cd8fbeb4edc5a99b725585edc02a16a8a0c503e
>>>>> # Parent 069a4813e8d6d7ec662d282a10f5f7062ebd817f
>>>>> SSL: disabled saving tickets to session cache.
>>>>>
>>>>> OpenSSL for TLSv1.3 tries to save tickets into session cache "because some
>>>>> applications just want to know about the creation of a session". To avoid
>>>>> trashing session cache with useless data, we do not save such sessions now.
>>>>>
>>>>
>>>> For the record, BoringSSL doesn't seem to call new_session_cb for TLSv1.3
>>>> at all, so there is no way to resume sessions with SSL_OP_NO_TICKET set.
>>>> In contrary, OpenSSL emits stateful tickets in this case, which contain
>>>> dummy session id used then as a session cache lookup key on server
>>>> (much like session ids in TLSv1.2)
>>>>
>>>> OTOH, without SSL_OP_NO_TICKET set, OpenSSL emits self-containing tickets
>>>> with enough info to resume session, so nothing to lookup in session cache.
>>>> The latter makes impractical storing something in session cache, except
>>>> to use the callback for things like tracking "the creation of a session".
>>>> Namely, OpenSSL puts session (i.e. something that SSL_get_session returns)
>>>> and supplementary info to session ticket message as the ticket value.
>>>
>>> It looks like you are trying to introduce "stateful tickets" and
>>> "self-containing tickets" terms, which is somewhat confusing
>>> unless carefully explained. OpenSSL itself tries to use terms
>>> "stateful tickets" and "stateless tickets", with the similar
>>> drawbacks.
>>
>> Indeed, OpenSSL SSL_OP_NO_TICKET documentation is what I refer to.
>> While OpenSSL terms may look odd, they are useful to describe the
>> difference (and tricks) in TLSv1.3 session resumption with and
>> without SSL_OP_NO_TICKET, as implemented to OpenSSL specifically.
>
> Sure. The problem is that OpenSSL's SSL_OP_NO_TICKET
> documentation is far from perfect, and I would rather avoid using
> it for anything but explanation of how SSL_OP_NO_TICKET works with
> TLSv1.3.
>
>>> A better explanation would be to follow generic term "session
>>> ticket", as originally introduced in RFC 4507 for TLS session
>>> resumption without server-side state.
>>>
>>> In these terms (as always used before introduction of TLSv1.3 and
>>> currently used in many places, including nginx own documentation
>>> and the source code) there are two basic mechanisms to resume
>>> sessions: server-side session cache and session tickets (used to
>>> resume sessions without server-side state).
>>>
>>> Without SSL_OP_NO_TICKET set, OpenSSL uses tickets as long as
>>> supported by the client.
>>>
>>> With SSL_OP_NO_TICKET set, OpenSSL does not use tickets, and uses
>>> server-side session cache instead (if configured).
>>>
>>> The only difference between TLSv1.3 and previous protocols is how
>>> session ids are sent to the client if server-side session cache is
>>> used. In case of SSL and TLS up to and including TLSv1.2, session
>>> ids are sent in the dedicated fields of the ServerHello and
>>> ClientHello handshake messages. In case of TLSv1.3, dedicated
>>> fields were removed, so session ids are sent in the
>>> NewSessionTicket messages ("a database lookup key" in terms of RFC
>>> 8446).
>>>
>>>> With these thoughts in mind, I think log could be clarified to emphasize:
>>>> - it's not tickets that are stored in cache
>>>> - with SSL_OP_NO_TICKET set TLSv1.3 session are still saved to lookup by id.
>>>
>>> Hope it is clear enough now.
>>
>> What I'd like to clarify is the difference between session and (session)
>> ticket applied to session cache. Ticket is a container used to envelope
>> session state (essentially, a session) and send in the NewSessionTicket
>> message "to resume sessions and avoid keeping per-client session state",
>> as seen in RFC 8446, 4.6.1 (and somewhat similar in 4507/5077).
>>
>> struct {
>> uint32 ticket_lifetime;
>> uint32 ticket_age_add;
>> opaque ticket_nonce<0..255>;
>> opaque ticket<1..2^16-1>;
>> Extension extensions<0..2^16-2>;
>> } NewSessionTicket;
>>
>> So it looks inappropriate to say that tickets are saved in cache.
>> OTOH, "ticket" can be seen a correct wording if speaking in terms
>> of NewSessionTicket ticket field, or in contrast to "session id"
>> synthesized by OpenSSL for the SSL_OP_NO_TICKET case in TLSv1.3.
>> In that sense, I'm fine with using "ticket" (not to say changing
>> "ticket" to "session" or "session state" brings a tautology).
>> However this looks not so important to spend more time on this,
>> I'm fine with either case.
>
> Sure, it would be more correct to say something like "OpenSSL
> tries to save sessions into session cache while using tickets for
> stateless session resumption" (mostly borrowed from
> SSL_OP_NO_TICKET documentation in OpenSSL 1.0.2[1]). I've used
> "tickets" instead of "sessions using tickets for stateless session
> resumption", as it's clearly shorter and only slightly less correct.
>
> [1] https://www.openssl.org/docs/man1.0.2/man3/SSL_set_options.html
>
> Updated with the above wording for clarity (still with the same
> summary line though, for simplicity):
>
> # HG changeset patch
> # User Maxim Dounin <mdounin at mdounin.ru>
> # Date 1664290542 -10800
> # Tue Sep 27 17:55:42 2022 +0300
> # Node ID e6b5a2aa0dd91a7f497014359e19458c78f480b3
> # Parent a423e314c22fe99fe9faf28f033c266426993105
> SSL: disabled saving tickets to session cache.
>
> OpenSSL tries to save TLSv1.3 sessions into session cache even when using
> tickets for stateless session resumption, "because some applications just
> want to know about the creation of a session". To avoid trashing session
> cache with useless data, we do not save such sessions now.
>
> diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
> --- a/src/event/ngx_event_openssl.c
> +++ b/src/event/ngx_event_openssl.c
> @@ -3818,6 +3818,23 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_
> ngx_ssl_session_cache_t *cache;
> u_char buf[NGX_SSL_MAX_SESSION_SIZE];
>
> +#ifdef TLS1_3_VERSION
> +
> + /*
> + * OpenSSL tries to save TLSv1.3 sessions into session cache
> + * even when using tickets for stateless session resumption,
> + * "because some applications just want to know about the creation
> + * of a session"; do not cache such sessions
> + */
> +
> + if (SSL_version(ssl_conn) == TLS1_3_VERSION
> + && (SSL_get_options(ssl_conn) & SSL_OP_NO_TICKET) == 0)
> + {
> + return 0;
> + }
> +
> +#endif
> +
> len = i2d_SSL_SESSION(sess, NULL);
>
> /* do not cache too big session */
>
Looks good.
--
Sergey Kandaurov
More information about the nginx-devel
mailing list