Thread (12 messages) flat view 12 messages, 6 authors, 2026-06-20

Re: [regression] Network failure beyond first connection after 69894e5b4c5e ("netfilter: nft_connlimit: update the count if add was skipped")

From: Fernando Fernandez Mancera <hidden>
Date: 2026-03-14 19:00:19
Also in: lkml, netfilter-devel, regressions, stable
Subsystem: netfilter, networking [general], the rest · Maintainers: Pablo Neira Ayuso, Florian Westphal, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

On 3/14/26 5:13 PM, Fernando Fernandez Mancera wrote:
Hi,

On 3/14/26 3:03 PM, Salvatore Bonaccorso wrote:
quoted
Control: forwarded -1 https://lore.kernel.org/ 
regressions/177349610461.3071718.4083978280323144323@eldamar.lan
Control: tags -1 + upstream

Hi

In Debian, in https://bugs.debian.org/1130336, Alejandro reported that
after updates including 69894e5b4c5e ("netfilter: nft_connlimit:
update the count if add was skipped"), when the following rule is set

    iptables -A INPUT -p tcp -m connlimit --connlimit-above 111 -j 
REJECT --reject-with tcp-reset

connections get stuck accordingly, it can be easily reproduced by:

# iptables -A INPUT -p tcp -m connlimit --connlimit-above 111 -j 
REJECT --reject-with tcp-reset
# nft list ruleset
# Warning: table ip filter is managed by iptables-nft, do not touch!
table ip filter {
         chain INPUT {
                 type filter hook input priority filter; policy accept;
                 ip protocol tcp xt match "connlimit" counter packets 
0 bytes 0 reject with tcp reset
         }
}
# wget -O /dev/null https://git.kernel.org/torvalds/t/linux-7.0- 
rc3.tar.gz
--2026-03-14 14:53:51--  https://git.kernel.org/torvalds/t/linux-7.0- 
rc3.tar.gz
Resolving git.kernel.org (git.kernel.org)... 172.105.64.184, 
2a01:7e01:e001:937:0:1991:8:25
Connecting to git.kernel.org (git.kernel.org)|172.105.64.184|:443... 
connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/ 
linux.git/snapshot/linux-7.0-rc3.tar.gz [following]
--2026-03-14 14:53:51--  https://git.kernel.org/pub/scm/linux/kernel/ 
git/torvalds/linux.git/snapshot/linux-7.0-rc3.tar.gz
Reusing existing connection to git.kernel.org:443.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/x-gzip]
Saving to: ‘/dev/null’

/dev/null                         [                         
<=>                    ] 248.03M  51.9MB/s    in 5.0s

2026-03-14 14:53:56 (49.3 MB/s) - ‘/dev/null’ saved [260080129]

# wget -O /dev/null https://git.kernel.org/torvalds/t/linux-7.0- 
rc3.tar.gz
--2026-03-14 14:53:58--  https://git.kernel.org/torvalds/t/linux-7.0- 
rc3.tar.gz
Resolving git.kernel.org (git.kernel.org)... 172.105.64.184, 
2a01:7e01:e001:937:0:1991:8:25
Connecting to git.kernel.org (git.kernel.org)|172.105.64.184|:443... 
failed: Connection timed out.
Connecting to git.kernel.org (git.kernel.org)| 
2a01:7e01:e001:937:0:1991:8:25|:443... failed: Network is unreachable.

Before the 69894e5b4c5e ("netfilter: nft_connlimit: update the count
if add was skipped") commit this worked.
Thanks for the report. I have reproduced this on upstream kernel. I am 
working on it.
This is what is happening:

1. The first connection is established and tracked, all good. When it 
finishes, it goes to TIME_WAIT state
2. The second connection is established, ct is confirmed since the 
beginning, skipping the tracking and calling a GC.
3. The previously tracked connection is cleaned up during GC as 
TIME_WAIT is considered closed.
4. count is therefore 0 and xt performs a drop.

There are two different approaches to fix this IMHO.

The first one would be to stop considering TIME_WAIT as closed. But that 
would artificially solve the issue.

The second one is to check what is the TCP status inside the 
nf_ct_is_confirmed() check and if it is SENT or RECV but confirmed there 
are two options - ore it is a retransmission or the ct was confirmed 
even before we tracked it. In both situations, perform an insert with a 
GC. Then we make sure no duplicate tracking is happening and the 
connection is tracked properly. The following diff fixes it, what do you 
think? I can send a formal patch if this solution is considered acceptable.
diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
index 00eed5b4d1b1..ae94e5d7e00b 100644
--- a/net/netfilter/nf_conncount.c
+++ b/net/netfilter/nf_conncount.c
@@ -78,6 +78,15 @@ static inline bool already_closed(const struct 
nf_conn *conn)
  		return false;
  }

+static inline bool tcp_syn_sent_or_recv(const struct nf_conn *conn)
+{
+	if (nf_ct_protonum(conn) == IPPROTO_TCP)
+		return conn->proto.tcp.state == TCP_CONNTRACK_SYN_SENT ||
+		       conn->proto.tcp.state == TCP_CONNTRACK_SYN_RECV;
+	else
+		return false;
+}
+
  static int key_diff(const u32 *a, const u32 *b, unsigned int klen)
  {
  	return memcmp(a, b, klen * sizeof(u32));
@@ -183,6 +192,9 @@ static int __nf_conncount_add(struct net *net,
  		 * might have happened before hitting connlimit
  		 */
  		if (skb->skb_iif != LOOPBACK_IFINDEX) {
+			if (tcp_syn_sent_or_recv(ct))
+				goto check_connections;
+
  			err = -EEXIST;
  			goto out_put;
  		}
Thanks,
Fernando.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help