Thread (12 messages) 12 messages, 5 authors, 21h ago

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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help