[PATCH nf] netfilter: conntrack: connection timeout after re-register
From: Francesco Ruggeri
Date: Mon Oct 05 2020 - 20:34:33 EST
I am sending out this patch mainly to clarify the source of a problem
I am seeing.
An idle tcp connection is timing out on a 4.19 kernel after
conntrack unregister/re-register. By playing with SO_KEEPALIVE
setsockopts on the client I can make it timeout in a few seconds.
I could not find any relevant commits in code after 4.19.
The problem seems to come from commit f94e63801ab2 ("netfilter:
conntrack: reset tcp maxwin on re-register").
Clearing maxwin of existing tcp connections on register, causes
tcp_in_window to set td_end to 1 less than it should if the first
packet it sees after the re-register is an outgoing keepalive packet,
causing it to later return false when getting packets from the peer
ack-ing the correct octet.
My iptables configuration on the client is:
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -p icmp -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 4445 -j ACCEPT
COMMIT
I unregister conntrack by using:
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
and then I restore the original one.
I do not see the issue with this patch, but I am not sure it is the
correct
Thanks,
Francesco Ruggeri
Fixes: f94e63801ab2 ("netfilter: conntrack: reset tcp maxwin on re-register")
Signed-off-by: Francesco Ruggeri <fruggeri@xxxxxxxxxx>
---
net/netfilter/nf_conntrack_proto_tcp.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index e8c86ee4c1c4..1ae1b7c78393 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -538,6 +538,12 @@ static bool tcp_in_window(const struct nf_conn *ct,
* Let's try to use the data from the packet.
*/
sender->td_end = end;
+ if (seq == end) {
+ /* This could be a keepalive packet with
+ * SEG.SEQ = SND.NXT-1.
+ */
+ sender->td_end++;
+ }
swin = win << sender->td_scale;
sender->td_maxwin = (swin == 0 ? 1 : swin);
sender->td_maxend = end + sender->td_maxwin;
--
2.28.0