/flags/iptables/iptables-m-conntrack-ctstate
iptables -m conntrack --ctstate ESTABLISHED,RELATED: allow reply traffic
- tool
- iptables / nftables
- command
- iptables
- flag
- -m conntrack --ctstate STATES
- default
- none (without the match, rules do not look at the connection state)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT accepts every packet that belongs to, or is related to, a connection the kernel's connection tracker already knows. It is the rule that makes a firewall stateful: you open only the ports for new incoming connections, and replies to traffic your host started (DNS answers, HTTP responses, package downloads) are allowed automatically. -m conntrack loads the conntrack match, and --ctstate takes a comma-separated list of states.
A minimal stateful INPUT chain
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -P INPUT DROPThe ESTABLISHED,RELATED rule comes first because it matches the vast majority of packets; order matters, see iptables -I vs -A. Set the DROP policy last, after the SSH rule exists, or a remote session is cut off.
States
The iptables-extensions manual defines these states for --ctstate:
| State | Meaning |
|---|---|
| NEW | The packet starts a new connection, or belongs to one that has not seen packets in both directions |
| ESTABLISHED | The packet belongs to a connection that has seen packets in both directions |
| RELATED | The packet starts a new connection associated with an existing one, such as an FTP data channel or an ICMP error |
| INVALID | The packet is associated with no known connection |
| UNTRACKED | The packet is not tracked, because a raw-table rule used -j CT --notrack |
| SNAT / DNAT | Virtual states: the original source or destination differs from the reply (NAT was applied) |
A ! before --ctstate negates the list, for example ! --ctstate NEW.
Other conntrack options
-m conntrack can also match --ctproto, --ctorigsrc/--ctorigdst, --ctreplsrc/--ctrepldst, the matching port options, --ctstatus (EXPECTED, SEEN_REPLY, ASSURED, CONFIRMED), --ctexpire and --ctdir ORIGINAL|REPLY. They are useful on NAT gateways, where the original and the translated addresses differ.
Pitfalls
- Module not available. On kernels or containers without the conntrack modules, the rule fails with No chain/target/match by that name.
- conntrack table full. Busy servers can exhaust
nf_conntrack_max; the kernel then logsnf_conntrack: table full, dropping packet. Raise the limit or exempt high-volume traffic with-j CT --notrackin the raw table. - Rules are not persistent. Save them as described in save and restore rules.
- nftables equivalent.
ct state established,related acceptdoes the same in nftables; see iptables vs nftables.
FAQ
What is the difference between -m state --state and -m conntrack --ctstate?
Both match the connection tracking state. The state match is the older, narrower module; conntrack is its superset and also matches original and reply addresses, ports and statuses. New rules should use -m conntrack --ctstate.
Why are replies to my outgoing connections dropped?
With a DROP policy on INPUT, reply packets need a rule that accepts them. Without an ESTABLISHED,RELATED accept, every reply is treated like unsolicited traffic and dropped, so DNS lookups and package downloads from the host fail.
Should I drop INVALID packets?
Usually yes: -m conntrack --ctstate INVALID -j DROP discards packets that belong to no known connection, such as stray TCP segments, before other rules see them.