From Christoph's Personal Wiki
Jump to: navigation, search

iptables is a user-space utility program that allows a system administrator to configure the tables provided by the Linux kernel firewall (implemented as different Netfilter modules) and the chains and rules it stores. Different kernel modules and programs are currently used for different protocols; iptables applies to IPv4, ip6tables to IPv6, arptables to ARP, and ebtables to Ethernet frames.

iptables requires elevated privileges to operate and must be executed by user root, otherwise it fails to function. On most Linux systems, iptables is installed as /usr/sbin/iptables and documented in its man pages, which can be opened using man iptables when installed. It may also be found in /sbin/iptables, but since iptables is more like a service rather than an "essential binary", the preferred location remains /usr/sbin.

The term iptables is also commonly used to inclusively refer to the kernel-level components. x_tables is the name of the kernel module carrying the shared code portion used by all four modules that also provides the API used for extensions; subsequently, Xtables is more or less used to refer to the entire firewall (v4, v6, arp, and eb) architecture.

The successor of iptables is nftables, which was merged into the Linux kernel mainline in kernel version 3.13, which was released on 19 January 2014.

Stateful filtering

  • Connection states (to match in the conntrack module): INVALID, NEW, ESTABLISHED, RELATED, UNTRACKED, SNAT, DNAT
  • Chain types (this option can either be the name of a user defined chain or any of the builtin chains): INPUT, FORWARD, OUTPUT, PREROUTING, POSTROUTING, SECMARK, CONNSECMARK
  • Jump types: ACCEPT, DROP, REJECT
  • Basic ruleset:
:OUTPUT ACCEPT [241:19144]
-A INPUT -p icmp -j ACCEPT 
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 53 -j ACCEPT
-A INPUT -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited 
-A FORWARD -j REJECT --reject-with icmp-host-prohibited 
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 --sport 63636 -s -j ACCEPT
  • Get a list of ICMP type names:
$ iptables -p icmp -h
  • The REJECT target rejects the packet. If you do not specify which ICMP message to reject with, by default, the server will send back "ICMP port unreachable" (type 3, code 3).
This is used to send back an error packet in response to the matched packet: otherwise it is equivalent to DROP so it is a terminating TARGET, ending rule traversal. This target is only valid in the INPUT, FORWARD, and OUTPUT chains, and user-defined chains which are only called from those chains. The following option controls the nature of the error packet returned:
--reject-with type
The type given can be:
icmp-admin-prohibited (*)
which return the appropriate ICMP error message (port-unreachable is the default). The option tcp-reset can be used on rules which only match the TCP protocol: this causes a TCP RST packet to be sent back. This is mainly useful for blocking ident (113/tcp) probes, which frequently occur when sending mail to broken mail hosts (which will not accept your mail otherwise).
(*) Using icmp-admin-prohibited with kernels that do not support it will result in a plain DROP instead of REJECT


  • Sample `iptables` ruleset:

# Dropping incoming connections that don't have explecit rules bellow
:INPUT DROP [68:4456]
:OUTPUT ACCEPT [1628:151823]

# Allow established connections for both public and private connections
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT

# Opening ports wide open
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 21 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 3306 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -p udp -m udp --dport 53 -j ACCEPT

# Opening a port to a specific IP
-A INPUT -p tcp -m tcp --dport 10000 -s -j ACCEPT

# Opening a port to a range of IPs
-A INPUT -p tcp -m tcp --dport 20000 -s -j ACCEPT

# Commmiting the rules to the firewall
# Set INPUT chain default policy to DROP
iptables -P INPUT DROP
# Flushes all rule in the filter table
iptables -F
# ACCEPT all packets from loopback interface
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# ACCEPT all NEW connections to tcp port 22
iptables -A INPUT -m state --state NEW -p tcp --dport 22 -j ACCEPT
# REJECT all packets from network
iptables -A INPUT -s -j REJECT
# ACCEPT all icmp traffic from
iptables -A INPUT -p icmp -s -j ACCEPT
# save rules
iptables-save > /etc/sysconfig/iptables
# print out saved rules
iptables -nvL

Network Address Translation (NAT)

  • The chains available in the filter table are: INPUT, FORWARD, OUTPUT
  • The chains available in the nat table are: PREROUTING, POSTROUTING, OUTPUT
  • Example:
$ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
$ iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source
$ iptables -t nat -A PREROUTING -i eth0 -m tcp -p tcp --dport 80 -j DNAT --to-destination
  • The DNAT target can only be used in the PREROUTING chain and the OUTPUT chain of the nat table.
  • To enable forwarding persistently across reboots, add net.ipv4.ip_forward=1 to /etc/sysctl.conf then run sysctl -p, or:
sysctl -w net.ipv4.ip_forward=1

Basic command options

Chain manipulation (three default chains, INPUT, FORWARD, OUTPUT, are always present):

  • Create a new chain (-N, --new-chain chain)
  • Delete an empty chain (-X, --delete-chain [chain])
  • Change the policy for a built-in chain (-P, --policy chain target)
  • List the rules in a chain (-L, --list [chain])
  • Flush the rules out of a chain (-F, --flush [chain])
  • Zero the packet and byte counters in all chains (-Z, --zero) (note: It is legal to specify the -L, --list (list) option as well, to see the counters immediately before they are cleared.)

Rule manipulation:

  • Append a new rule to a chain (-A, --append chain rule-specification)
  • Delete a rule at some position in a chain (-D, --delete chain rule-specification)
packet starts a new communication, adds a rule to the state tracking table
any packet that matches a rule in the state tracking table
traffic "related" in some way to ESTABLISHED traffic; protocols like SSH, FTP, etc.
packet cannot be identified; normally these should be rejected or dropped

NOTE: Running the `iptables` command changes the netfilter kernel module rules in memory, but will not persist across a reboot.

Running `service iptables save` will take the current rules in memory and write them to /etc/sysconfig/iptables which is read during system boot. Run instead:

service iptables restart

Help (-h)


iptables -[AD] chain rule-specification [options]
iptables -[RI] chain rulenum rule-specification [options]
iptables -D chain rulenum [options]
iptables -[LFZ] [chain] [options]
iptables -[NX] chain
iptables -E old-chain-name new-chain-name
iptables -P chain target [options]
iptables -h (print this help information)


Either long or short options are allowed.

--append -A chain 
append to chain
--delete -D chain 
delete matching rule from chain
--delete -D chain rulenum 
delete rule rulenum (1 = first) from chain
--insert -I chain [rulenum] 
insert in chain as rulenum (default 1=first)
--replace -R chain rulenum 
replace rule rulenum (1 = first) in chain
--list -L [chain] 
list the rules in a chain or all chains
--flush -F [chain] 
delete all rules in chain or all chains
--zero -Z [chain] 
zero counters in chain or all chains
--new -N chain 
create a new user-defined chain
--delete-chain -X [chain] 
delete a user-defined chain
--policy -P chain target 
change policy on chain to target
--rename-chain -E old-chain new-chain 
change chain name, (moving any references)


--proto -p [!] proto 
protocol: by number or name, eg. 'tcp'
--source -s [!] address[/mask] 
source specification
--destination -d [!] address[/mask] 
destination specification
--in-interface -i [!] input name[+] 
network interface name ([+] for wildcard)
--jump -j target 
target for rule (may load target extension)
--goto -g chain 
jump to chain with no return
--match -m match 
extended match (may load extension)
--numeric -n 
numeric output of addresses and ports
--out-interface -o [!] output name[+] 
network interface name ([+] for wildcard)
--table -t table 
table to manipulate (default: 'filter')
--verbose -v 
verbose mode
print line numbers when listing
--exact -x 
expand numbers (display exact values)
[!] --fragment -f 
match second or further fragments only
try to insert modules using this command
--set-counters PKTS BYTES 
set the counter during insert/append
[!] --version -V 
print package version.


Netmask Bit Values
Addrs Bits Pref Class Mask
0 /32
2 1 /31
4 2 /30
8 3 /29
16 4 /28
32 5 /27
64 6 /26
128 7 /25
256 8 /24 1C
512 9 /23 2C
1K 10 /22 4C
2K 11 /21 8C
4K 12 /20 16C
8K 13 /19 32C
16K 14 /18 64C
32K 15 /17 128C
64K 16 /16 1B
128K 17 /15 2B
256K 18 /14 4B
512K 19 /13 8B
1M 20 /12 16B
2M 21 /11 32B
4M 22 /10 64B
8M 23 /9 128B
16M 24 /8 1A
32M 25 /7 2A
64M 26 /6 4A
128M 27 /5 8A
256M 28 /4 16A
512M 29 /3 32A
1024M 30 /2 64A
2048M 31 /1 128A
4096M 32 /0 256A

ICMP datagram types

see: RFC 1700 (Assigned Numbers)
ICMP Datagram Types
Type number iptables mnemonic Type description
0 echo-reply Echo Reply
3 destination-unreachable Destination Unreachable
4 source-quench Source Quench
5 redirect Redirect
8 echo-request Echo Request
11 time-exceeded Time Exceeded
12 parameter-problem Parameter Problem
13 timestamp-request Timestamp Request
14 timestamp-reply Timestamp Reply
15 none Information Request
16 none Information Reply
17 address-mask-request Address Mask Request
18 address-mask-reply Address Mask Reply

Type Of Service (TOS)

Suggested Uses for TOS Bitmasks
TOS ANDmask XORmask Suggested Use
Minimum Delay 0x01 0x10 ftp, telnet, ssh
Maximum Throughput 0x01 0x08 ftp-data, www
Maximum Reliability 0x01 0x04 snmp, dns
Minimum Cost 0x01 0x02 nntp, smtp

Example script



# flush iptables
iptables -F
iptables -t nat -F
iptables -t mangle -F

# loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# policies
iptables -P INPUT DROP
iptables -P FORWARD DROP

iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P OUTPUT ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

iptables -t mangle -P PREROUTING ACCEPT
iptables -t mangle -P OUTPUT ACCEPT

# allow related incoming
iptables -I INPUT 1 -m state --state ESTABLISHED,RELATED -j ACCEPT

# programs and stuff (add a line for each service you want to allow)

# SSH on local network
iptables -A INPUT -s $CLASS_A -p tcp --destination-port 22 -j ACCEPT

# apache server (on all interfaces/networks)
iptables -A INPUT -p tcp --destination-port 80 -j ACCEPT

# samba + network share
iptables -A INPUT -s $CLASS_A -p tcp --destination-port 137 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p udp --destination-port 137 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p tcp --destination-port 138 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p udp --destination-port 138 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p tcp --destination-port 139 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p udp --destination-port 139 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p tcp --destination-port 445 -j ACCEPT
iptables -A INPUT -s $CLASS_A -p udp --destination-port 445 -j ACCEPT

Map external IP address onto an internal one

Let's say your external IP address is and your internal IP address is, then:

-A PREROUTING -d -j DNAT --to-destination
-A POSTROUTING -s -j SNAT --to-source

You can then view the results with

iptables --list -n -t nat -v



  • Find your external interface:
$ ip route ls via dev eth0  metric 10 dev eth0  proto kernel  scope link  src  metric 10 dev eth0  proto kernel  scope link  src  metric 10 dev eth0  scope link  metric 10 dev lo  scope link
default via dev eth0  metric 10

The last line shows eth0 to be your external interface.

  • Determine the IP address of your external interface:
$ ip addr ls dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 100
   link/ether 00:19:d1:4f:22:60 brd ff:ff:ff:ff:ff:ff
   inet brd scope global eth0
   inet brd scope global eth0:0
   inet6 fe80::219:d1ff:fe4f:2260/64 scope link
      valid_lft forever preferred_lft forever
  • So, the IP address of the external interface is

See also

External links

Free firewall software

Tutorials / Howtos / Examples / etc.