Applies to: Linux systems using the iptables command interface Last reviewed: 2026-07-14
iptables is still widely used, but many current Linux distributions use the nftables framework underneath or prefer the native nft command. Confirm whether the host uses iptables-legacy, iptables-nft, firewalld, UFW, or native nftables before changing rules.
[!DANGER] A remote firewall change can immediately lock you out. Keep an existing privileged session open, save the current rules, schedule an automatic rollback when possible, and verify console or out-of-band access.
iptables --version
update-alternatives --display iptables 2>/dev/null || true
nft list ruleset
systemctl status firewalld --no-pager
ufw status verbosesudo iptables-save > "iptables-backup-$(date +%Y%m%d-%H%M%S).rules"
sudo iptables -S
sudo iptables -L --numeric --verbose --line-numbers
sudo iptables -t nat -S
sudo iptables -t mangle -SUse -C to check whether a rule already exists:
sudo iptables -C INPUT -p tcp --dport <port> -j ACCEPTPrefer conntrack rather than the older state match:
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -i lo -j ACCEPTAllow SSH from a management network:
sudo iptables -A INPUT \
-p tcp \
-s <management-cidr> \
--dport 22 \
-m conntrack --ctstate NEW \
-j ACCEPTAllow a TCP or UDP service:
sudo iptables -A INPUT -p tcp --dport <port> -j ACCEPT
sudo iptables -A INPUT -p udp --dport <port> -j ACCEPTRules are evaluated in order. Insert a rule at a specific position when required:
sudo iptables -I INPUT <line-number> <rule-specification>Delete by exact rule specification when possible:
sudo iptables -D INPUT -p tcp --dport <port> -j ACCEPTOr review numbered rules and then delete a line:
sudo iptables -L INPUT --numeric --line-numbers
sudo iptables -D INPUT <line-number>Line numbers change after deletion, so list the chain again before deleting another rule.
Inspect current policies before changing them:
sudo iptables -SExample policy change:
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPTWarning
Add required management, loopback, established-session, and service rules before setting a default DROP policy.
sudo iptables -A INPUT \
-m limit --limit 5/min --limit-burst 10 \
-j LOG --log-prefix "iptables-input-drop: " --log-level warningAn unconditional LOG rule can flood system logs.
Enable IPv4 forwarding using persistent system configuration rather than a one-off command:
sysctl net.ipv4.ip_forwardMasquerade traffic leaving an interface:
sudo iptables -t nat -A POSTROUTING -o <egress-interface> -j MASQUERADEDestination NAT:
sudo iptables -t nat -A PREROUTING \
-i <ingress-interface> \
-p tcp --dport <external-port> \
-j DNAT --to-destination <destination-ip>:<destination-port>Also permit the forwarded traffic in the FORWARD chain and validate the return path.
sudo iptables -A INPUT \
-p tcp --dport <port> \
-m conntrack --ctstate NEW \
-m limit --limit <rate>/second --limit-burst <burst> \
-j ACCEPT- An iptables destination using a DNS name is resolved when the rule is created; it does not continuously track DNS changes.
- Redirecting TCP port 80 to 443 does not add TLS. The application on the destination port must actually speak TLS.
- Dropping all ICMP can break Path MTU Discovery and troubleshooting. Filter specific types only with a documented reason.
- Flushing rules remotely without a tested rollback can disconnect the host.
Persistence is distribution-specific. On Debian-based systems using iptables-persistent:
sudo iptables-save | sudo tee /etc/iptables/rules.v4 >/dev/null
sudo ip6tables-save | sudo tee /etc/iptables/rules.v6 >/dev/nullVerify the persistence service and restore behavior before rebooting.
Validate a saved ruleset in a lab when possible, then restore:
sudo iptables-restore < iptables-backup.rulesFor remote maintenance, use iptables-apply when available because it can automatically roll back unconfirmed changes:
sudo iptables-apply