All information pulled out from this link for personal notes and study.

How iptables work

The iptables work mainly in Internet layer and Transport layer. However, iptables can also work in Application layer, but it is not intended to do so.


Allows packet processing in specific ways. There are four types of tables:

  1. The filter table: Default and most popular table. It is used to decide whether a packet should be allowed or denied to reach its destination.
  2. The mangle table: Allows you to change packet headers.
  3. The nat table: Allows you to route packets to different hosts on a NAT by changing source and destination address of a packet.
  4. The raw table: Allows you to work with packets before the kernel starts tracking its state.
  5. The security table: Used by SELinux to implement SELinux policies.


Each table contains few chains which are attached to them. They allow you to inspect and filter traffic at various points. This is the list of chains iptables use:

  • PREROUTING chain: Applies rules for packets that just arrived on the network interface. Supports nat, mangle, and raw tables.
  • INPUT chain: Applies rules for packets just before they are given to a local process. Supports mangle and filter tables.
  • OUTPUT chain: Applies rules for packets right after they are produced by a process. Supports raw, mangle, nat, and filter tables.
  • FORWARD chain: Applies rules for packets that are routed through the current host. Supports mangle and filter tables.
  • POSTROUTING chain: Applies rules for packets as they leave the network interface. Supports nat and mangle tables.
Image from www.booleanworld.com


They decide whether packet is allowed or rejected. Commonly used terminating targets are:

  • ACCEPT: iptables accepts the packet
  • DROP: iptables drops the packet. For client, he cannot tell if this host exists.
  • REJECT: iptables rejects the packet. For TCP, it sends “connection reset” packet, and for UDP or ICMP, it sends “destination host unreachable”

Setting default policies

Default policy governs how iptables handles packets that pass all rules. Imagine a system is candy factory and all bad candies are on a production line. If set to DROP, workers will pick up only good candies, and bad ones are going to a trash bin. Similarly, with policy set to DROP, a packet comes to a system and is waiting for firewall rules. Packet that matches a rule gets picked up from production line and the rest of them are dropped. Here is how to set this:

# iptables --policy INPUT DROP
# iptables --policy OUTPUT DROP
# iptables --policy FORWARD DROP

Or, we can set iptables to ACCEPT all packets that passed rules. For example, ACCEPT all packets except those with specified IP address. If one is found, rule will pick it up and it won’t find its way to the last rule, which ACCEPTs them. Lets use our candy factory analogy again. This time, all candies on production line are good. However, if bad candy is passing by, a worker will pick it up and throw out of the production. Good candies will make to the packaging and will be distributed. Here is how to set ACCEPT default policy:

# iptables --policy INPUT ACCEPT
# iptables --policy OUTPUT ACCEPT
# iptables --policy FORWARD ACCEPT

If set to REJECT, packets that find their way to the end of a list will be rejected. However, this rule sends back error message to a client. In this way, client will know firewall blocked his packet. In contrary, when set to DROP, firewall does not send any feedback to the client. It simply drops the packet and moves on.

Allowing or blocking connections

Important flags:

-tSpecify the table where rule will apply to
-AApped this rule (INPUT) to the list of existing rules in INPUT chain
-sSet source IP that you want to block
-jiptables will reject traffic with REJECT target (sends packet back to the client)
If you want iptables to not respond, use DROP target.
-dBlock output traffic to this IP address
-LList all rules within the chain
-nDon’t resolve names
-FFlush all rules within the chain
-RReplace single rule (modify it)

Blocking IP address

If you want to block an incoming IP address, you would block all incoming packets coming from that IP address. To add this rule to the INPUT chain of the filter table, use this:

# iptables -t filter -A INPUT -s -j REJECT

Block range of IP addresses with CIDR notation, for example:

# iptables -t filter -A INPUT -s -j REJECT

Or, if you want to block output traffic to that IP address, use OUTPUT chain, and –d to specify destination:

# iptables -t filter -A OUTPUT -d -j DROP

Listing rules

If you want to see all rules (-L), from filter table (-t filter), and numbered (–line-number), and disable DNS lookup (-n) use the following command:

# iptables -L -n -t filter

Deleting rules

To remove a rule, replace -A with -D:

# iptables -t filter -D INPUT -s -j REJECT

or delete rule by its rule number:

# iptables -t filter -D INPUT 3

When you remove a rule from a chain, in this case INPUT chain, first delete ones with highest numbers (those at the end of list). For example:

# iptables -t filter -D INPUT 20
# iptables -t filter -D INPUT 9
# iptables -t filter -D INPUT 6

To remove all rules from a particular chain, use this:

# iptables -t filter -F INPUT

Inserting and replacing rules

Since the chain apply rules one by one (from first rule to the last), we must make sure they are properly positioned. So,the rule that is blocking all traffic from /24 subnet, cannot be before rule that whitelists single IP from that subnet. It must be the other way around. First, you whitelist an IP address, and then block the entire subnet:

Protocols and modules

To block all incoming TCP traffic you would use -p tcp flag, like so:

# iptables -t filter -A INPUT -p tcp -j DROP

To block all incoming traffic to port 22 (SSH) from IP range, you would type this:

# iptables -t filter -A INPUT -p tcp -m tcp --dport 22 -s -j DROP

Let’s digest this formula from above:

-t filterApply the following for filter table
-A INPUTNow, append this rule to INPUT chain
-p tcpSpecify port type (TCP in this case)
-m tcpLoad TCP module (multiport for multiple ports)
–dportAnd all incoming packets going to port 22 (–dports for multiple ports)
-s source IP / range
-j DROPDROP them

TCP Connection Tracking Module

iptables have a module that can control packet behavior from the state of a connection. Here are the states:

NEWThis state represents first packet of a connection (HTTP request for example)
ESTABLISHEDThis state is used for packets that are part of an existing connection. For a connections to be in this state,
it must receive a reply from the other host
RELATEDThis state is used for packets that are related to another ESTABLISHED connection. For a packet that is part of an existing connection, but it requests new connection.
INVALIDThis state means the packet doesn’t have proper state.
DNATThis state is used to show packets whose destination address was changed by rules in nat table
SNATThis state is used to show packets whose source address was changed by rules in nat table.
# iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

If we set a INPUT chain policy to accept, like this (which is default rule):

[root@arch ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Then, all traffic that comes to our system will be accepted. However, we can also use DROP to ban all incoming connections to our system, like so:

# iptables -P INPUT DROP

If doing this, we should ban all incoming traffic, from any IP, from any port. However, this will also restrict us to use all services, and also to use Internet.

Saving changes

Changes we make to iptables rules will be removed next time iptables service gets restarted. To save changes, run /sbin/iptables-save command

Remove rules

To remove all configured rules, and go back to default ones, use -F (flush):

# iptables -F

Leave a Reply