Skip to content
LinkState
Go back

NAT expiry that looks like chronic packet loss

Introduction to Retransmission Storms

Definition and Causes

A retransmission storm occurs when an endpoint repeatedly retransmits packets that are dropped because an intermediate stateful device (NAT, firewall, load‑balancer) has removed its translation or connection‑tracking entry while the flow is still active. The surviving host interprets the lack of ACK as loss and triggers TCP retransmission timers; if the state remains absent, an exponential back‑off loop ensues, consuming bandwidth and CPU.

Typical causes

Impact on Network Performance


Understanding Translation State Expiration

Translation State Overview

Translation state is the data structure a middlebox creates to map an internal address:port to an external address:port (NAT) or to track a connection’s lifecycle (conntrack, stateful firewall). For TCP, the entry typically contains:

Expiration Mechanisms and Timers

Most stateful implementations use idle timers that reset on each packet seen in either direction. When the timer expires, the entry is removed and any subsequent packet is treated as new or invalid.

Linux netfilter/conntrack

Cisco ASA/FTD

Palo Alto

Juniper SRX

If no packet matches the tuple before the timer fires, the state is cleared. Subsequent packets from the endpoint that still believes the connection is alive are treated as out‑of‑state and are either dropped or, in the case of NAT, cause address translation failure leading to ICMP unreachable or TCP RST.

Effects of Idle Periods on Translation State

During an idle period, no packets reset the timer. If the idle interval exceeds the configured timeout, the translation/conntrack entry disappears. When the application resumes sending data:


Identifying Retransmission Storms

Symptoms and Indicators

Diagnostic Tools and Techniques

ToolUsageWhat to Look For
`tcpdump -i any -nn -s0 -w /tmp/storm.pcap ‘tcp[tcpflags] & (tcp-syntcp-acktcp-rst) != 0’`
ss -ti state established '( dport = :22 or sport = :22 )'Show per‑socket TCP inforetransmits field rising rapidly.
conntrack -L -p tcp --dport 22List conntrack entries for SSHEntries disappearing after idle period; timeout field near zero.
iptables -L -v -n -t natView NAT counterspkts increasing on MASQUERADE but bytes low due to drops.
nft list rulesetnftables equivalentSame as above.
tcpick -C -yP -r /tmp/storm.pcapRe‑assemble streamsApplication data missing after idle gap.
ethtool -S eth0NIC statsRising tx_retransmits or rx_drop.
prometheus node_exporter + netstat alertsLong‑term monitoringAlert on node_tcp_retransmits_total rate > threshold.

Log Analysis and Error Messages


Troubleshooting Retransmission Storms

Step‑by‑Step Troubleshooting Process

  1. Confirm the symptom – Capture traffic on both sides of the stateful device; verify retransmits occur only after an idle gap.
  2. Locate the stateful device – Identify where NAT/conntrack/firewall sits (traceroute, ip route get, or ACL logs).
  3. Check timeout values – Retrieve the relevant idle timers (see section 4). Compare with observed idle period.
  4. Correlate logs – Match timestamp of state expiration log with first retransmit.
  5. Validate symmetry – Ensure forward and reverse paths traverse the same stateful node (check for asymmetric routing, ECMP, or policy‑based routing).
  6. Test with a keep‑alive – Send a minimal packet (e.g., TCP zero‑window probe or application‑level keep‑alive) shorter than the timeout; observe if storm disappears.
  7. Adjust or workaround – Increase timeout, enable TCP keep‑alives on hosts, or implement idle‑timeout bypass (e.g., iptables -t raw -I PREROUTING -p tcp --dport 22 -j NOTRACK for specific flows).
  8. Verify – Repeat capture; retransmits should drop to baseline (< 1 %).
  9. Document – Record original and new timeout values, reason for change, and any side effects.

Common Causes and Solutions

CauseSymptomFix
NAT TCP timeout too short (e.g., 30 s)Storm after ~30 s idleIncrease /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established to match application keep‑alive or raise to ≥ 1 h.
Application lacks keep‑aliveStorm after any idle > timeoutEnable TCP keep‑alive (net.ipv4.tcp_keepalive_time=60, net.ipv4.tcp_keepalive_intvl=10, net.ipv4.tcp_keepalive_probes=6) or use application‑level keep‑alive.
Asymmetric routing causing state loss on return pathOnly outbound retransmits, inbound ACKs arriveSymmetrize routing (static routes, policy‑based routing, or disable ECMP for affected flows).
Stateful device overload dropping entries earlyStorm under high connection countIncrease conntrack hash size (net.netfilter.nf_conntrack_max) or upgrade hardware; enable nf_conntrack_expect_max if needed.
Mis‑matched UDP timeout (e.g., 5 s) for media streamsStorm on RTP silence periodsRaise UDP timeout (nf_conntrack_udp_timeout) or enable udp timeout never on firewall for media ports.

Advanced Troubleshooting Techniques


Configuring Translation State Timeout Values

Overview of Timeout Values and Settings

Timeout values dictate how long a state entry survives without seeing a packet. They are protocol‑ and state‑specific. Adjusting them prevents premature expiration while balancing memory usage.

Key knobs (Linux)

On firewalls, similar timers exist under timeout commands (ASA, PAN‑OS, SRX).

CLI Examples for Configuring Timeout Values

Linux (sysctl)

# View current TCP established timeout (seconds)
sysctl net.netfilter.nf_conntrack_tcp_timeout_established
# Set to 2 hours (7200s) – persists until reboot
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=7200
# Make permanent
echo "net.netfilter.nf_conntrack_tcp_timeout_established=7200" >> /etc/sysctl.d/99-conntrack.conf
sysctl -p /etc/sysctl.d/99-conntrack.conf

Linux (nftables)

# nftables can expose conntrack limits via the 'ct' timeout table (kernel 5.6+)
nft add table ip filter
nft add chain ip filter input { type filter hook input priority 0 \; }
# Example: set TCP established timeout to 7200s for packets matching port 22
nft add rule ip filter input tcp dport 22 ct timeout set 7200

Cisco ASA

# Show current timeout
show running-config all | include timeout
# Change TCP timeout to 2 hours
timeout conn 7200

Palo Alto (PAN‑OS)

# Configure via CLI
configure
set deviceconfig setting session tcp-timeout 7200
commit

Juniper SRX

# Set TCP session timeout to 2 hours
set security flow tcp-session timeout 7200
commit

Share this post on:

Previous Post
Where the parser belongs in an AI NetOps stack
Next Post
Container restart silently detached the veth tooling