linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Simulator
  • Knowledge base
  • Interview prep
Index
Categories
All entries
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
home/linux/kb/Commands/cmd-iptables

kb/commands ── Commands ── advanced

iptables: netfilter rules (legacy)

iptables is the userland interface for netfilter. Five tables (filter/nat/mangle/raw/security), chains INPUT/OUTPUT/FORWARD/PRE/POSTROUTING, and jump targets ACCEPT/DROP/MASQUERADE. Legacy, but still widely deployed.

view as markdownaka: iptables, iptables-legacy, iptables-nft, ip6tables

Why you still need to know iptables in 2026

RHEL 8/9 and Debian 11/12 have formally moved to nftables, but the iptables command on those systems is often just a frontend (iptables-nft), and old scripts keep working. On Alpine, Ubuntu LTS before 22.04, embedded systems, and a lot of legacy infrastructure, it is still plain iptables. Docker still writes rules through iptables. Knowing it means being able to read production.

For new code, use [[cmd-nft|nft]]: one syntax instead of iptables/ip6tables/arptables/ebtables, with support for sets, namespaces, and atomic updates.

Architecture: tables and chains

A packet travels through netfilter hooks in the kernel. iptables attaches chains to those hooks, grouped into tables by purpose:

TableWhat it does
filterallow or block traffic (default)
nataddress translation (SNAT, DNAT, [[nat
mangleheader modification (TOS, TTL, MARK)
rawbefore conntrack (NOTRACK to exclude traffic)
securitySELinux MAC labels

Standard chains and where they fire:

               ┌─PREROUTING─→─routing─┬─FORWARD──→─POSTROUTING─┐
 in iface ────┤                       │                        ├──→ out iface
              └────────────────────────→ INPUT → local proc OUTPUT
  • PREROUTING (raw, mangle, nat): fires immediately on ingress
  • INPUT (filter, mangle): packets destined for the local host
  • OUTPUT (raw, mangle, nat, filter): locally generated packets
  • FORWARD (filter, mangle): transit packets (requires ip-forwarding)
  • POSTROUTING (mangle, nat): fires just before egress

Basic syntax

iptables [-t TABLE] -A CHAIN [-s SRC] [-d DST] [-p PROTO] [--dport N] [-i IFACE] -j TARGET
OptionWhat it does
-A CHAINappend: add to the end of the chain
-I CHAIN [N]insert at position N (1 means the top)
-D CHAIN Ndelete by number; or -D CHAIN <rule> for an exact match
-L [CHAIN]list (usually with -n -v --line-numbers)
-F [CHAIN]flush: remove all rules
-P CHAIN POLICYdefault policy (ACCEPT/DROP)
-N CHAINcreate a custom chain
-X CHAINdelete an empty chain

Targets (jump)

TargetWhat it does
ACCEPTlet the packet through
DROPsilently discard
REJECTdiscard and send ICMP unreachable
LOGlog to dmesg/syslog (--log-prefix)
MASQUERADESNAT with automatic source-IP selection
SNAT --to-source IPsource NAT
DNAT --to-destination IP[:PORT]destination NAT
MARK --set-mark Nmark for policy routing
<custom-chain>jump to a custom chain
RETURNreturn from the current chain

Common recipes

Basic host firewall

bash
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -j ACCEPT                                    # localhost
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT                        # ssh
iptables -A INPUT -p tcp --dport 443 -j ACCEPT                       # https
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT          # ping

Without the conntrack rule, outgoing connections will not receive replies. This is the first thing people forget.

NAT for a container network

bash
echo 1 > /proc/sys/net/ipv4/ip_forward       # see [[ip-forwarding]]
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o eth0 -j MASQUERADE

Port forwarding

bash
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.5:80
iptables -A FORWARD -p tcp -d 10.0.0.5 --dport 80 -j ACCEPT

Rate-limiting brute-force attempts

bash
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
         -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
         -m recent --update --seconds 60 --hitcount 5 --name SSH -j DROP

No more than 5 new SSH connections from a single IP per minute.

Saving and restoring rules

Changes made with iptables -A survive only until reboot. You must save them explicitly:

bash
iptables-save > /etc/iptables/rules.v4         # export current state
iptables-restore < /etc/iptables/rules.v4      # import (atomic)
ip6tables-save > /etc/iptables/rules.v6        # IPv6: separate command!

Distribution-specific notes:

  • Debian/Ubuntu: apt install iptables-persistent saves to /etc/iptables/rules.v[46] and loads on boot.
  • RHEL: iptables-services, systemctl enable iptables ip6tables.

iptables-legacy vs iptables-nft

On modern distributions, the iptables command is a shim over nftables:

bash
iptables --version
# iptables v1.8.7 (nf_tables)   ← nft backend
# iptables v1.8.7 (legacy)       ← old xt_ backend

You cannot mix them. Rules in legacy and in nft live in separate namespaces. If Docker and kube-proxy write rules through different backends, you can end up with a hole in your firewall. The fix: update-alternatives --config iptables, or use iptables-legacy / iptables-nft explicitly.

ip6tables and ebtables

IPv6 has a separate rule set and a separate command:

bash
ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT

Ethernet bridge filtering uses ebtables (at L2). nftables unifies all of this under a single nft command, which is a real advantage.

When something goes wrong

  • Locked yourself out of SSH: the first INPUT DROP rule with no explicit permit for port 22. Before any rules-up script, run at +5 'iptables -F', or work through a console or serial connection.
  • Permission denied: iptables requires root and the NET_ADMIN capability.
  • Rule not matching: check the order with iptables -L INPUT -n -v --line-numbers. The first match wins; byte counters show what passed through.
  • NAT not working: missing ip_forward=1, missing MASQUERADE, or missing a FORWARD permit.
  • Conntrack overflow: dmesg | grep nf_conntrack shows table full. Raise nf_conntrack_max via [[cmd-sysctl|sysctl]], or remove stateful traffic from conntrack with -t raw -j NOTRACK.
  • iptables-restore silently skipped part of the file: a syntax error in the middle. It reads line by line; everything before the error is applied atomically, everything after is not. Check the exit code.

Alternatives

  • [[cmd-nft|nftables]]: the modern successor
  • firewalld: a high-level daemon, abstraction over nft/iptables (RHEL default)
  • ufw: simplified frontend over iptables (Ubuntu)
  • shorewall: an older rules compiler

§ команды

bash
iptables -L INPUT -n -v --line-numbers

List the INPUT chain with numeric addresses, packet/byte counters, and line numbers

bash
iptables -t nat -L -n -v

Show the NAT table: see what is doing MASQUERADE or DNAT

bash
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

Allow SSH: the first rule to add when setting up a host firewall

bash
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE

NAT for subnet 10.0.0.0/24 on outgoing interface eth0

bash
iptables-save > /etc/iptables/rules.v4

Snapshot current rules. Save before making any changes.

bash
iptables -F && iptables -X && iptables -P INPUT ACCEPT

Reset everything to ACCEPT defaults. Use locally for debugging, not on production.

bash
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m limit --limit 3/min -j ACCEPT

Rate-limit new SSH connections to 3 per minute. A simple anti-brute-force measure.

§ см. также

  • cmd-nftnft: modern firewall (nftables)`nft` is the single CLI for modern netfilter. Replaces iptables/ip6tables/ arptables/ebtables. Structure: tables, chains, rules.
  • firewalld-vs-nftablesfirewalld vs nftables: what to choosefirewalld is a daemon wrapper with zones, services, and rich rules; the backend since RHEL 8 is nftables. Plain nft gives more control, sets, and atomic reload. firewalld fits desktop and multi-zone, nft fits a server fleet.
  • natNAT: Network Address TranslationNAT rewrites the src or dst address of a packet at a router. Masquerade is the common case: the src IP is replaced with the router's outbound address so hosts on a private network can reach the public internet.
  • ip-forwardingIP Forwarding: Turn a Host into a RouterLinux does not forward packets between interfaces by default. Enable it with `sysctl net.ipv4.ip_forward=1`. Without this, NAT, VPN routing, and any forwarding will not work.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies