[nginx] QUIC: "handshake_timeout" configuration parameter.

Roman Arutyunyan arut at nginx.com
Wed Apr 10 11:57:33 UTC 2024


Hi,

> On 10 Apr 2024, at 10:57 AM, Vladimir Homutov <vl at inspert.ru> wrote:
> 
> On Tue, Apr 09, 2024 at 03:02:21PM +0400, Roman Arutyunyan wrote:
>> Hello Vladimir,
>> 
>> On Mon, Apr 08, 2024 at 03:03:27PM +0300, Vladimir Homutov via nginx-devel wrote:
>>> On Fri, Sep 22, 2023 at 03:36:25PM +0000, Roman Arutyunyan wrote:
>>>> details:   https://hg.nginx.org/nginx/rev/ad3d34ddfdcc
>>>> branches:
>>>> changeset: 9158:ad3d34ddfdcc
>>>> user:      Roman Arutyunyan <arut at nginx.com>
>>>> date:      Wed Sep 13 17:59:37 2023 +0400
>>>> description:
>>>> QUIC: "handshake_timeout" configuration parameter.
>>>> 
>>>> Previously QUIC did not have such parameter and handshake duration was
>>>> controlled by HTTP/3.  However that required creating and storing HTTP/3
>>>> session on first client datagram.  Apparently there's no convenient way to
>>>> store the session object until QUIC handshake is complete.  In the followup
>>>> patches session creation will be postponed to init() callback.
>>>> 
>>> 
>>> [...]
>>> 
>>>> diff -r daf8f5ba23d8 -r ad3d34ddfdcc src/event/quic/ngx_event_quic.c
>>>> --- a/src/event/quic/ngx_event_quic.c	Fri Sep 01 20:31:46 2023 +0400
>>>> +++ b/src/event/quic/ngx_event_quic.c	Wed Sep 13 17:59:37 2023 +0400
>>>> @@ -211,6 +211,8 @@ ngx_quic_run(ngx_connection_t *c, ngx_qu
>>>>     qc = ngx_quic_get_connection(c);
>>>> 
>>>>     ngx_add_timer(c->read, qc->tp.max_idle_timeout);
>>>> +    ngx_add_timer(&qc->close, qc->conf->handshake_timeout);
>>>> +
>>> 
>>> It looks like I've hit an issue with early data in such case.
>>> See the attached patch with details.
>> 
>> Indeed, there's an issue there.
>> 
>>> While there, I suggest a little debug improvement to better track
>>> stream and their parent connections.
>>> 
>>> 
>> 
>>> # HG changeset patch
>>> # User Vladimir Khomutov <vl at wbsrv.ru>
>>> # Date 1712576340 -10800
>>> #      Mon Apr 08 14:39:00 2024 +0300
>>> # Node ID 6e79f4ec40ed1c1ffec6a46b453051c01e556610
>>> # Parent  99e7050ac886f7c70a4048691e46846b930b1e28
>>> QUIC: fixed close timer processing with early data.
>>> 
>>> The ngx_quic_run() function uses qc->close timer to limit the handshake
>>> duration.  Normally it is removed by ngx_quic_do_init_streams() which is
>>> called once when we are done with initial SSL processing.
>>> 
>>> The problem happens when the client sends early data and streams are
>>> initialized in the ngx_quic_run() -> ngx_quic_handle_datagram() call.
>>> The order of set/remove timer calls is now reversed; the close timer is
>>> set up and the timer fires when assigned, starting the unexpected connection
>>> close process.
>>> 
>>> The patch moves timer cancelling right before the place where the stream
>>> initialization flag is tested, thus making it work with early data.
>>> 
>>> The issue was introduced in ad3d34ddfdcc.
>>> 
>>> diff --git a/src/event/quic/ngx_event_quic_streams.c b/src/event/quic/ngx_event_quic_streams.c
>>> --- a/src/event/quic/ngx_event_quic_streams.c
>>> +++ b/src/event/quic/ngx_event_quic_streams.c
>>> @@ -575,6 +575,10 @@ ngx_quic_init_streams(ngx_connection_t *
>>> 
>>>     qc = ngx_quic_get_connection(c);
>>> 
>>> +    if (!qc->closing && qc->close.timer_set) {
>>> +        ngx_del_timer(&qc->close);
>>> +    }
>>> +
>>>     if (qc->streams.initialized) {
>>>         return NGX_OK;
>>>     }
>>> @@ -630,10 +634,6 @@ ngx_quic_do_init_streams(ngx_connection_
>>> 
>>>     qc->streams.initialized = 1;
>>> 
>>> -    if (!qc->closing && qc->close.timer_set) {
>>> -        ngx_del_timer(&qc->close);
>>> -    }
>>> -
>>>     return NGX_OK;
>>> }
>> 
>> This assumes that ngx_quic_init_streams() is always called on handshake end,
>> even if not needed.  This is true now, but it's not something we can to rely on.
>> 
>> Also, we probably don't need to limit handshake duration after streams are
>> initialized.  Application level will set the required keepalive timeout for
>> this.  Also, we need to include OCSP validation time in handshake timeout,
>> which your removed.
>> 
>> I assume a simpler solution would be not to set the timer in ngx_quic_run()
>> if streams are already initialized.
> 
> Agreed, see the updated patch:
> 
> 
> <early_close_timer2.diff>

Thanks, committed!

----
Roman Arutyunyan
arut at nginx.com




-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20240410/2ee336a0/attachment.htm>


More information about the nginx-devel mailing list