How to Use Iptables

1. Introduction

First we must mention that iptables is a Linux kernel firewall, which is why we can categorize it with the picture below:


The picture is presented so we can better imagine how firewalls and iptables firewall are connected with information security in general. I've also written an article about abstract categories that divided the whole information security field into abstract categories: here, and I further divided the "Packet Filtering" abstract category as can be seen in this article: here.

If you read the mentioned articles then it should be clear what those categories in the above picture mean, and no further explanation of them is needed. Now we will move into our iptables discussion.

2. Iptables Installation

First, we need to install and start the iptables firewall:

# apt-get install iptables

# service ufw start

In Ubuntu ufw service is used to start/stop the firewall. UFW stands for Universal FireWall, which uses the iptables command and allows us to easily manage our firewall on a Linux machine.

3. Accepting/Denying the Packets

We already know that all packets coming to our machine must also pass through our iptables firewall, which determines if the packet is accepted or denied – to do that, iptables must look up its internal rules to decide what to do with the packet.

We can present the whole scheme of how a single packet travels from the client through the Internet to the server, which uses iptables to accept/deny the packet. In the picture below we can see that the client sends the packet to the server through the Internet. When the server receives the packet, it forwards it on to the Linux kernel, which passes it to the iptables firewall, which decides whether the packet should be accepted or denied. If the packet is accepted it is passed to the application that is waiting for that packet, otherwise it is dropped and the application will never see the packet.


We've presented the basic scheme of what happens when the server receives the packet, but we still don't know anything about the iptables internals. How does it work, how does it decide whether to accept or deny a packet?

First we must know that iptables firewall consists of three tables/queues:

Mangle Queue: used for mangling packets and to change Differentiated Services Code Point (DSCP) or Type of Service (ToS) and Time to Live (TTL) fields in the IP header. We can also append a special mark to the packet, which is later used to route packets differently depending upon the mark they have – this can be useful for bandwidth limiting. Thus this table is responsible for changing certain bits in TCP header.

  • Filter Queue: Responsible for packet filtering.
  • Nat Queue: Responsible for network address translation (NAT).

Additionally, each queue has its chains. Let's name all of the chains for each queue:

  • Filter Queue: FORWARD, INPUT, OUTPUT.

A great job was already done with representing the queues, their chains and chain functions, so we won't try to reinvent the wheel. Rather we'll represent the picture of a table taken from the URI [1]:


We can see that the above picture does a great job of representing all three queues: mangle, filter, and nat, as well as their corresponding chains with a description of each chain and table. The default FILTER queue has three chains defined. The FORWARD chain filters packets that need to be sent to another network in the firewall's jurisdiction. The INPUT chain filters packets that want to enter the network, while the OUTPUT chain filters packets that want to leave the network.

When specifying firewall rules we must specify the table and its chain for each rule.

To make this a bit clearer, let's take a look at the picture below – also taken from [1] – that demonstrates what happens when a packet from the Internet arrives at the firewall's interface on Network A and wishes to proceed to Network B:** **


When a packet arrives at Network A's entry point, it first goes through the Mangle-PREROUTING, which can modify the values in the TCP packet, but it usually doesn't. The packet then goes to Nat-PREROUTING, which takes care of address translation before the packet is routed anywhere else. Afterwards the packet is routed. At this point the packet can carry data for the firewall itself, or some other network. If the former, the packet must pass through the Mangle-INPUT, before being filtered by the rules in Filter-INPUT, which filters packets coming from the Internet. If a packet is valid and isn't denied in the filtering process, then it's handled over to the intended application on the firewall, which needs to reply. The reply is filtered by the Mangle-OUTPUT to change some fields in the TCP header and Nat-OUTPUT to do network address translation. After that the packet is handed over to the Filter-OUTPUT, Mangle-POSTROUTING and Nat-POSTROUTING before being sent on the Internet.

But if the packet is not destined for the firewall itself, but needs to go to the Network B, then it must go through filters Mangle-FORWARD, Filter-FORWARD, Mangle-POSTROUTING, Nat-POSTROUTING before reaching its destination.

The scheme in the above picture applies when iptables is installed on a separate machine, which serves as a firewall router that accepts all the packets coming from the Internet and going to the Internet. To represent that a little bit further, let's look at the picture below, which corresponds to the above iptables filtering packet flow:


The iptables firewall is represented with a yellow node. The "Data for the firewall" decision node in the previous picture corresponds to the packets coming into the network destined for the iptables firewall itself, which must handle them. The Network B corresponds to all the other nodes in the network topology, namely: A1, A2, A3, A4, B1, B2, B3 as well as additional switch and router.

But there are times when we need to implement the iptables rules on one server only. Let's say we run the same topology as presented above, but the iptables is not running on an entry point of our network, but on one server only. The new topology can be seen in the picture below:


In this case the iptables is running on a server node B2. This is important, because most of the features of iptables firewall are not needed anymore. The Nat queue is used for network address translation, but do we need it in such cases? No, we don't, because how would the packet otherwise come to the destination server if the network address translation wasn't being done already – it's being done by the entry node router, like Linksys WRT54G. So in this case, we don't need to use the Nat queue when implementing iptables rules. Since we probably also don't want to modify TCP header values, we can omit the Mangle queue as well. This leaves just the Filter queue, which has FORWARD, INPUT and OUTPUT chains. But even the FORWARD chain is not needed, since the packets need not to be forwarded to another NIC, but are intended for current server node. This leaves just Filter-INPUT and Filter-OUTPUT chains for which we must specify filtering rules.

4. Filtering Rules

When a certain packet enters the iptables firewall, it's inspected against all applicable rules in different chains in a queue. Each firewall rule must determine what to do with the packet. Actions used on each packet are the following:

  • ACCEPT: the packet is immediately handed over to the end application for further processing.
  • DROP: the packet is immediately dropped and is not processed further.
  • LOG: the packet information is logged (syslog) and iptables continues processing the next rule in a table.
  • REJECT: the same as DROP, but will also return an error message to the originating host which sent the packet.
  • DNAT: do a destination network address translation by rewriting the destination IP in the IP header.
  • SNAT: do a source network address translation by rewriting the source IP in the IP header. The source IP address is dynamic.
  • MASQUERADE: do a source network address translation by rewriting the source IP in the IP header. The source IP address is that of a firewall.

The help page of the iptables command is appended below and the important options are presented in bold font:

# iptables -h

iptables v1.4.13

Usage: iptables -[ACD] chain rule-specification [options]

iptables -I chain [rulenum] rule-specification [options]

iptables -R chain rulenum rule-specification [options]

iptables -D chain rulenum [options]

iptables -[LS] [chain [rulenum]] [options]

iptables -[FZ] [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.

<strong> --append      -A chain </strong>         Append to chain

--check      -C chain         Check for the existence of a rule

--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 [rulenum]]     List the rules in a chain or all

--list-rules      -S [chain [rulenum]]     Print the rules in a chain or
all chains

<strong> --flush      -F [chain] </strong>         Delete all rules in
chain or all chains

--zero      -Z [chain [rulenum]]     Zero counters in chain or all

--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


--ipv4      -4             Nothing (line is ignored by

--ipv6      -6             Error (line is ignored by iptables-restore)

<strong>--proto      -p proto</strong>         protocol: by number or
name, eg. `tcp'

<strong>--source      -s address[/mask]</strong>     source

<strong>--destination -d address[/mask]    </strong>    destination

--in-interface -i input name         network interface name ([+] for

<strong>--jump      -j target </strong>         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

<strong> --table      -t table </strong>         table to manipulate
(default: `filter')

--verbose -v             verbose mode

--line-numbers             print line numbers when listing

--exact      -x             expand numbers (display exact values)

--fragment -f             match second or further fragments only

--modprobe=<command>         try to insert modules using this command

--set-counters PKTS BYTES         set the counter during insert/append

--version -V             print package version.

This will all become a little bit clearer with a few examples.

5. Examples

All the examples in this section will be specified as if the iptables firewall was implemented on a single server machine and not as a boundary firewall on the network. This is why we won't be needing the Nat and Mangle queues, but only the Filter queue – in which we should use only the INPUT and OUTPUT chains to filter packets.

5.1. Allow SSH access

To allow only ssh connections to the server, we need to execute the following command to add a new filtering rule into the INPUT Filter queue:

# iptables -t filter -A INPUT -p TCP -i wlan0 --dport 22 -j ACCEPT

Explanation of used options:

  • t: add the rule into the filter table
  • A: append the rule to the INPUT chain
  • p: the referenced rule, which is TCP in our case
  • i: the input interface
  • dport: destination port
  • j: the action to take when all the criterion for specific filtering rule match

This rule will accept any TCP connection coming in on interface wlan0 from any IP address and any port number, but destined to port number 22 with any destination IP address.

6. Conclusion

After we've modified all the firewall rules we need to save them, so they will also be applied next time when the computer is rebooted.

# iptables-save > firewall-config

# iptables-restore < firewall-config

The latter command can easily be added into the /etc/rc.local configuration file, which would restore the iptables rules upon computer reboots.


[1] Linux Firewalls Using iptables, accessible on

iptables -P chain target [options]