Re: [PATCH net] netfilter: nf_nat_masquerade: recalculate TCP TS offset when port is randomized
From: xietangxin <hidden>
Date: 2026-07-01 14:09:29
Also in:
lkml, netfilter-devel, stable
On 6/29/2026 11:23 PM, Florian Westphal wrote:
xietangxin [off-list ref] wrote:quoted
Problem observed in Kubernetes environments where MASQUERADE target with --random-fully is configured by default. after commit 165573e41f2f ("tcp: secure_seq: add back ports to TS offset") TCP short connection QPS dropped from ~20000 to ~10000. This added source and destination ports into TS offset calculation. However, with MASQUERADE --random-fully, when multiple internal connections (e.g sport 10000,20000) are mapped to the same external port (e.g 30000), their TS offsets are calculated as ts_offset(10000) and ts_offset(20000). If the server reuses the TIME_WAIT slot from the first connection, there is a chance that ts_offset(20000) < ts_offset(10000), breaking TSval monotonicity for the same 4-tuple and causing RST packets: Client -> Server 24870 -> 80 [SYN] TSval=2294041168 Server -> Client 80 -> 24870 [ACK] TSecr=2846236456 Client -> Server 24870 -> 80 [RST] Seq=855605690 After nf_nat_setup_info() successfully assigns a new randomized source port, recalculate the TS offset using the new port and update the SYN packet's TSval accordingly.I don't think this is related to masquerade but to snat (port address rewrite) in general. I think you could place your new helper in nf_nat_core.c and call it from nf_nat_l4proto_unique_tuple() once we've found a usable tuple: 668 another_round: 669 for (i = 0; i < attempts; i++, off++) { 670 *keyptr = htons(min + off % range_size); 671 if (!nf_nat_used_tuple_harder(tuple, ct, attempts - i)) ... here. 672 return; 673 }
Hi Florian,
Thank you for the insightful feedback. You are absolutely right that
this issue is releated to SNAT with port rewrite, rather masquerade.
Shifting the helper down to nf_nat_l4proto_unique_tuple() as you suggested
encounters a structural roadblock. we don't have access to the skb there.
Adding skb to all intermediate callers (like nf_nat_setup_info, get_unique_tuple)
would severely pollute the core NAT APIs.
would it be acceptable to place this logic in nf_nat_inet_fn() before do_nat?
963 do_nat:
..here
964 return nf_nat_packet(ct, ctinfo, state->hook, skb);
965
966 oif_changed:
967 nf_ct_kill_acct(ct, ctinfo, skb);
968 return NF_DROP;
969 }
Best regards,
Tangxin Xie