Re: Re: [PATCH nf-next] netfilter: conntrack: tcp: use UNACK timeout for non-closing RST packets
[email protected] Wed, 29 Jul 2026 23:51:52 +0800 (GMT+08:00)
| Newsgroups | gmane.comp.security.firewalls.netfilter.devel |
|---|---|
| Message-ID | <39facdf3.aa91.19fae933b17.Coremail.zhangmh25@mails.tsinghua.edu.cn> |
Hi Florian, Thanks, yes, the explicit CLOSE branch was redundant. I tested the narrower version which only uses UNACK when the RST does not close the conntrack entry: else if (unlikely(index == TCP_RST_SET && new_state == TCP_CONNTRACK_ESTABLISHED)) timeout = timeouts[TCP_CONNTRACK_UNACK]; With this version, non-exact in-window RSTs stay in ESTABLISHED and get the UNACK timeout, while exact RSTs still fall through to timeouts[new_state] and therefore keep using the CLOSE timeout. Using new_state != TCP_CONNTRACK_ESTABLISHED would also catch the exact-RST case and make it use UNACK instead of CLOSE, so I used the ESTABLISHED-only condition in v2. I have sent v2 with this simplification. Thanks, Minghao Zhang > -----Original Messages----- > From: "Florian Westphal" <[email protected]> > Send time:Wednesday, 29/07/2026 23:09:03 > To: "Minghao Zhang" <[email protected]> > Cc: [email protected], [email protected], "Jianjun Chen" <[email protected]> > Subject: Re: [PATCH nf-next] netfilter: conntrack: tcp: use UNACK timeout for non-closing RST packets > > Minghao Zhang <[email protected]> wrote: > > Commit be0502a3f2e9 ("netfilter: conntrack: tcp: only close if RST > > matches exact sequence") keeps an established conntrack entry in > > ESTABLISHED when an in-window RST does not match the expected sequence > > number exactly, so the endpoint can validate the RST with a challenge > > ACK. > > > > The timeout selection nevertheless uses the CLOSE timeout for every RST > > packet. The bug is that timeout selection is based on the packet type, > > not on the state transition result: even when RST validation keeps > > new_state in ESTABLISHED, the timeout is still forced to > > TCP_CONNTRACK_CLOSE. > > > > Linux TCP independently rate limits challenge ACKs per socket. A second > > non-exact RST can therefore arrive after the first challenge ACK has > > restored the timeout but before the rate limit expires. The second RST > > lowers the timeout to 10 seconds again while the endpoint suppresses the > > second challenge ACK, allowing the conntrack entry to expire while both > > TCP endpoints remain established. > > > > Using the ESTABLISHED timeout for non-exact RSTs would avoid this short > > expiration window, but it could also retain stale entries for the > > five-day default because conntrack cannot reliably match the endpoint's > > exact TCP state. > > > > Use the UNACK timeout for RST packets that do not move the conntrack > > entry to TCP_CONNTRACK_CLOSE. Exact-match RSTs and accepted RST packet > > trains still use the CLOSE timeout because their state transition result > > is CLOSE. This avoids the exploitable 10-second expiration window for > > non-exact RSTs while preserving the short timeout for RSTs that > > conntrack accepts as closing the flow. > > Hmm. > > > timeout = timeouts[TCP_CONNTRACK_RETRANS]; > > - else if (unlikely(index == TCP_RST_SET)) > > + else if (unlikely(index == TCP_RST_SET && > > + new_state == TCP_CONNTRACK_CLOSE)) > > timeout = timeouts[TCP_CONNTRACK_CLOSE]; > > Is this needed? If new state is TCP_CONNTRACK_CLOSE, the existing > else branch will: > else > timeout = timeouts[new_state]; > > > + else if (unlikely(index == TCP_RST_SET)) > > + timeout = timeouts[TCP_CONNTRACK_UNACK]; > > AFAICS this is enough: > - else if (unlikely(index == TCP_RST_SET)) > - timeout = timeouts[TCP_CONNTRACK_CLOSE]; > + else if (unlikely(index == TCP_RST_SET && new_state != TCP_CONNTRACK_ESTABLISHED)) > + timeout = timeouts[TCP_CONNTRACK_UNACK]; > > Could you test this? Thanks!