iptables and iprules

iptables and ipchains

Recall the network diagram from Linux Firewall Management Tools Overview shows the process flow of a packet and when the packet may be acted upon by iproute, iprule, or iptables.

iptables is Ubuntu's built-in firewall. It uses a set of rules to influence network traffic passing to, from, and through it. Ubuntu 16.04.x uses iptables version 1.6. To verify your iptables version, execute the iptables command like so:

iptables --version

iptables may perform stateful packet inspection and mangle (manipulate) the packet to some extent, and has some control over the packet's path through the server. It differs from ip route and ip rule in that it cannot deliver a packet to a destination. Rather, iptables is only concerned with how the packet is handled inside of a server container, based upon the type of traffic.

Terminology Confusion

Some internet sources commingle the concepts of iptables and ipchains, inadvertently providing inaccurate explanations of how they function. Quite frankly, I can't blame other authors for misconstruing some of the concepts at work here. The architects of netfilter and the ip tools suite could have saved the public countless hours of confusion if they'd had the foresight to resist the temptation of recycling similar terms in the evolution of Linux networking. The relationship between ipchains and iptables is particularly confusing to many.

My intention is not to bad-mouth any other specific sources, but rather to draw attention to this fact. The distinction between iptables and ipchains is confusing, and this fact has been caused in no small part by the use of similar nomenclature to describe different processes and functions within netfilter and the Linux kernel. Generally speaking, Linux has a sordid history of old code never completely going away. Integrating new processes with legacy code always has been and continues to be the norm.

Chains and Tables

iptables processes packets based on what are called chains - a carry-over from ipchains - that preceded iptables. Chains refer to netfilter's hooks into the networking stack. Tables are rule-set containers inside netfilter.

Every packet is placed onto a chain based on the type of destination of the packet. From iptables' perspective, chains serve as conduits of process flow. Within that flow you will find hooks into various tables. Those tables are effectively repositories of rules. The net effect is chains appear to act as rule-sets, however that's not quite correct. In reality they are pointers to the rules stored in tables. When a packet traverses a chain, specific tables are referenced based on the particular chain. Within each referenced table, only rules that correlate to the active chain will be applied to the current packet.

This is the fundamental architecture behind chains and tables, and you should bear that in mind as you read through this section. These core concepts are not fully understood and incorrectly proselytized by many online references. If you can wrap your head around it, you will have no issues following the logic flow of rules as they are applied to packets and connections. The problem I find is many authors do not fully understand the concepts and get confused about chains in particular. Chains don't control rules. They control the process, which tables are applied, and when.


Chains are all about process flow. A good way to think of chains is as collections of rules or pointers to rules. Chains determine the order in which sets of rules will be implemented. You cannot manipulate the processing order of the default chains, remove them, or change whether or not each chain is activated. What you can do is manipulate the rules in each chain (discussed in Tables).

Chains encapsulate the top-level process flow of packet filtering. ipchains preceded iptables and created the chains concept. It had just three chains, or processes: INPUT, OUTPUT, and FORWARD. They were named for the type of network traffic. At its most basic level of navigation, a network packet can only be travelling through a server along one of these three paths, and that is still true today. The INPUT chain relates to an incoming packet addressed to the current server. The OUTPUT chain is the opposite. It relates only to packets originating with the local host that are leaving the current sever. And FORWARD is reserved for packets that are neither and are simply traversing through the current server, where both source and destination are other servers.

Older iterations of iptables and netfilter used only the three aforementioned chains. The current version of netfilter has five built-in chains: INPUT, OUTPUT, FORWARD, PRE-ROUTING, and POST-ROUTING. These reflect the possible high level filtering routes of any packet traversing the server. iptables also allows the creation of custom chains.

INPUT, OUTPUT, and FORWARD are primary chains, and reflect the three possible functional routes in which a packet may traverse the server: leaving (output), arriving (input), or traversing through the server (forward). Every packet goes through just ONE of those processes. The FORWARD chain is normally applicable only to firewalls and gateways (routers). You may generally ignore it if your server is not a router or firewall.

PREROUTING and POSTROUTING are routing chains, which work a little differently. All packets go through either PREROUTING (incoming) or POSTROUTING (outgoing), based solely on the direction of travel of the packet. The Pre and Post-Routing chains bookend the other chains, meaning they occur before or after the other chain. With the exception of the Forward chain, only one or the other will be called before or after the primary chains.

Here's a summary view of the five permanent chains:

Chain Description
INPUT Local host is destination
OUTPUT Local host is source
FORWARD Host is neither source nor destination; applies to both INPUT and OUTPUT
PREROUTING Executed before INPUT or FORWARD chains are processed
POSTROUTING Executed after FORWARD or OUTPUT chains are processed

Default Chains

You may view the current status of iptables by executing this command:

iptables -L

By default this command will display the contents of the FILTER table in each chain. If you have not established any rules yet, your display will look like this:

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

Roughly translated, each chain has a blanket ACCEPT policy, and all of the tables in each chain are empty. All traffic is allowed by default in each chain. That means all packets will be accepted or allowed to move through each chain.

Notice the PREROUTING and POSTROUTING chains do not appear when you list the current iptables rules. I haven’t found a concrete explanation for why this is the case, but I suspect it is due to a combination of two factors: 1) A legacy characteristic of the migration to iptables from ipchains, because ipchains only used the three primary chains; and 2) by default the contents of the Filter table are displayed, which is only present in the three primary chains.

One of the major improvements from ipchains to iptables was limiting a packet to just a single primary chain, whereas the older ipchains method processed every packet through every primary chain, even if a chain did not apply to the packet. This architectural change alone resulted in significant speed improvements when iptables was introduced. Regardless, viewing the output shown above for the three primary chains is rarely useful since not all chains are displayed.

How To Create Custom Chains

When is a chain not a chain? When you create one! Custom chains are possible, but they don't function in quite the same manner as the built-in chains. A custom chain acts like a programming sub-routine. When you call a custom chain, all of its rules will be acted upon, in priority order. When you create a new chain, you are creating a new rule container; a sub-set of rules. After you've created a custom chain, you populate it with rules. You may then reference the rules in that custom chain, and when that chain is called, those rules will be acted upon.

The logic flow confuses many people because it's different from the normal chains/tables process. Just like the default, static chains, when creating a new rule for your custom chain you must specify an associated table. However, custom chains may only be associated with the Filter table. Since the Filter table is the default condition when no table parameter is specified in a rule, you might as well leave it out of the commands for your custom chain.

Now, if you are astute, by now you should be wondering; How is it possible to access these new, custom chains? After all, there is no mechanism within the permanent chains to reference one another (and to do so would be contradictory to their function). The answer is by using a JUMP command that diverts the process flow to a non-terminating TARGET. This directs the current logic flow onto your custom chain.

Custom chains are very useful in complicated iptables configurations. They make it easier to organize and segment rules, grouping sets of oft repeated commands you want to replicate in different tables, different chains, or under different circumstances.

Custom Chain Examples

Take a look at an example of a custom chain. Let's say you want to branch to a set of rules in your custom chain called icmp-chain when an ICMP packet is received on the INPUT chain.

  1. First, create your new chain.

    iptables -N icmp-chain

  2. Append a command to the end of the INPUT chain that says to jump to the "icmp-chain" named chain when the packet protocol is ICMP. Note this will automatically be placed into the FILTER table. There's no choice on which table is utilized. However, you must indicate which primary or routing chain is associated with the redirection.

    iptables -A INPUT -p icmp -JUMP icmp-chain


    iptables -A INPUT -p icmp -j icmp-chain

  3. Create at least one rule in your new chain. This one says to send an ICMP echo response

    iptables -A icmp-chain -p icmp --icmp-type echo-reply -j ACCEPT

  4. Don't forget to place a RETURN jump at the end of your chain, which will jump back to the next command in sequence after the command that called the custom chain. This is a good preventive practice. If a RETURN command does not exist and no actions are executed prior to reaching the end of the custom chain, netfilter will be unable to return back to where it started prior to jumping to the custom chain, the packet will be stuck and the connection will hang until it times out with a no-response error.

    iptables -A icmp-chain -j RETURN

So, what's the point in custom chains?

The most common purpose of custom chains is to more clearly segment rules in a firewall. The process makes it easier to organize and call groups of rules that only pertain to specific circumstances. When those circumstances occur, the custom chain is called and its rules are operated upon.


Tables comprise groups of instructions defined in a particular order. Tables are called by chains. You cannot alter the built-in chains and tables or their order-of-execution.

You may think of chains as highways inside your server. They are able to direct traffic flow, but cannot modify the packets. The next layer down are tables: the filtering workhorse of iptables. They cannot direct traffic flow, but they may modify the packet. The end result is all filtering rules can be located in one place and called by the packet directional control processes (chains) as needed. A table simply contains a set of packet filtering instructions (but cannot alter which chain a packet traverses).

iptables has are five (5) static tables. They are: RAW, MANGLE, NAT, FILTER, and SECURITY. Of these, the Raw and Security tables are rarely used except within firewall servers. There is not a 1:1 correlation between iptables tables and netfilter chains.

Recall that chains represent conduits a packet travels through, depending on its source and destination. These default tables are called at various stages by each of the aforementioned chains. And just like the fact all packets don't traverse every chain, not all tables are called by every chain. This chart identifies which tables are called by each chain, and the order the tables are called:

Chain Table Processing Order
INPUT Mangle, Filter, Security, NAT
OUTPUT Raw, CONNTRACK, Mangle, NAT, Filter, Security
FORWARD Mangle, Filter, Security

Here’s another viewpoint demonstrating the tables associated with each default iptables chain:

Table Associated Chains

I'm sure you noticed there are duplicate entries in these charts. Why is that? This is where the relationship between chains and tables begins to get a bit tricky. When constructing commands in iptables, they reside in tables. Yet commands are not executed until a chain is processed. Each chain calls the tables associated with the chain in sequential order, as expressed in the charts above. As each table is called, netfilter searches the table's contents for commands that match the current chain. Those matching commands are executed in order based on their priority in the table.

It's interesting to note some of the nuances of the default tables. For instance, only the Mangle table is called by every chain. NAT is available in every chain except FORWARD, though only Source or Destination NAT are available in any given chain, depending on which chain is being processed. The Security table always follows the Filter table, and both are only available in the INPUT, OUTPUT, and FORWARD chains. This is interesting considering most rules on a firewall server normally reside in the Filter table. And as mentioned previously, firewalls are typically the only instance you're likely to see the Security and Raw tables utilized.

Table Priority

Tables contain commands that influence the characteristics and/or the destination of a packet. In a firewall, your rules go in these tables. For the purpose of routing packets to a VPN, this is where rules are established to make that happen.

Let's examine the roles of each table:

Table Description
Raw Specialized packet handling of unusual situations
NAT New connections go here after Raw table; modify based on IP address or port
Mangle Specialized packet alteration
Filter Traditional firewall rules; filter based on data type and source/destination
Security Specialized use for access control; gets called last if at all

RAW is rarely used and always called first. The Raw table allows a connection to circumvent other filtering. The NAT table can be used to modify IP address and port data in the packet. The Mangle and Filter tables perform the vast majority of packet manipulation. If you don't specify a table name in an iptables command, the Filter table will be used by default. The Security table is rarely relevant outside of firewall or router applications and it will be ignored in this guide as it is irrelevant for our purposes. If no table is specified in a relevant iptables command, the Filter table is presumed by default. Not all tables are used in every process. When writing rules to influence VPN vs. non-VPN traffic, ensure you understand the order your rules will be processed, in order to facilitate the desired result. If a rule is post-ceded by a number, it indicates the order of operation (i.e. action #1 is performed before #2, etc.). Remember, if you don't specify a table, an instruction will be placed in the Filter table by default.

Table Processing

Each table is called by one or more chains. Here are the chains associated with each built-in table.

Table Associated Chains

Studying the list above, you can see how the Mangle table is the most prevalent because it is called in every chain. Likewise, note the OUTPUT chain is the only one that calls every table.

High-Level Table Tips

Each of the five tables in iptables has unique qualities and deserve a bit of attention explaining why they exists and how they differ from one another.


The FILTER table is the default table loaded into the Linux kernel. If you do not apply any rules to a fresh Linux installation, the Filter table will still be present and populated with a very basic set of firewall rules. Its job is to filter packets with broad brush strokes.

You may think of the Filter table as a series of traffic lights that only have the red (stop) and green (go) colors. It contains only black-and-white rules that when applied, allow a packet to either continue or halt its journey. When one thinks generally of firewall rules, this is normally where those rules are stored and managed. A server and even a dedicated firewall can happily exist applying only the Filter table.


In routing terms, "mangling" means the process of altering IP header packets before, during, or after routing. The iptables MANGLE table's job is to match packets against chains of rules and mark the packet so it can be routed appropriately. A common use of the Mangle table is to make adjustments to the priority of a packet based on Quality of Service (QoS)[1] and Type of Service (ToS) rules.

The MANGLE table is unique in two regards: 1) All of its rules are analyzed; and 2) It is the only table that appears in all five chains.

All Rules Are Analyzed

Typically, when a rule inside a table is a match, that rule is executed and the packet then moves forward in the routing process. However, the Mangle table behaves differently from all other tables. The Mangle executes every matching rule against the current packet. This is one reason why applying packet filters in the Mangle table is strongly discouraged. Although it can be used for this purpose, the practice is dangerous and one must be extremely careful in rule application if one chooses to do so.


NAT is an acronym for Network Address Translation. The NAT table's job is - as it name implies - to translate network addresses. This includes the capability of masking outgoing packets so as to hide their origin within the local network. It also keeps track of packets that have been "masked" as such, sent out to an upstream router (e.g. somewhere on the Internet), and returned (requiring reverse translation so they can be sent to the originating server on the local area network).


The RAW table has a very narrowly defined role. Its sole purpose is to remove a packet from stateful inspection. This means the modified packet is not evaluated with regards to any other packet, and is evaluated discretely. This function may be applied to incoming or outgoing packets. This can be dangerous and use of the RAW table should be considered an advanced topic. Misuse can and will result in disrupted communications because the server will treat discrete packets as independent connections.


The SECURITY table allows setting SELinux context to packets. It is perhaps the most esoteric of all the tables, the least likely to be utilized, and arguably the least understood. In a nutshell, it allows applying Mandatory Access Control (MAC) policies to a packet. However, it requires a pre-requisite Linux security module that is not present on most Linux distributions, making its use limited.

Astute observers may have noticed the Security table rarely appears on iptables networking diagrams. Why? For starters, it did not even exist until early 2008, while iproute2 has been around since 2000. Second, by default it is not applicable.[2]

If your Linux distribution does not contain SELinux, iptables will ignore any attempts to affect the Security table.

The Security table's purpose is to set SELinux security context on packets pertaining to SELinux - an acronym for Security-Enhanced Linux (a Linux kernel security module). One of the hallmarks of Linux is the fact its kernel is built on a modular framework. A primary benefit of Linux is its ability to apply strict enforcement of access control policies and functions. SELinux applies a flexible framework of Mandatory Access Control (MAC) levers to the server's kernel. This allows capabilities such as controlling access to server resources by network connection and packet states.

SELinux is not embedded in Linux by default. It is enabled by default in some Linux distributions (such as Fedora and Red Hat), but not in others (such as Ubuntu). Alternatives also exist. For instance, AppArmor, which as of this writing is compatible with the following Linux distributions: Arch Linux, CentOS, Debian, Gentoo, openSUSE, Pardus, PLD, and Ubuntu.

When present, the Security table is processed immediately after the Filter table.

Viewing Existing iptables Rules

Here's the syntax if you want to display information about your chains and tables via the command line. Remember, the default table (if you don't specify one) is filter and the default chain (if none is specified) is to display data from all chains.

iptables -t {table name} -L {chain}iptables -t {table name} -L {chain}

For example,

iptables -t filter -L INPUT

Is the same as:

iptables -L INPUT

And will produce a result similar to this:

Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere ctstate ESTABLISHED
ACCEPT all -- anywhere anywhere
DROP all -- anywhere anywhere ctstate INVALID
UDP udp -- anywhere anywhere ctstate NEW

What do those headings mean?

Heading Meaning
target Specifies what should be done with the packet when a rule matches
prot IP options; rarely used
source Source IP address; or "anywhere" is not defined
destination Destination IP address; or "anywhere" if not defined

You can also use the -S switch, which prints basically the same data as -L except it the actual rules are shown, just as if you'd type them into a file or command line (the iptables command prefix is omitted). For example:

iptables -S mychain

Would yield something like:

-A MYCHAIN -p tcp -m tcp --dport 22 -j ACCEPT

As you can see, the -S switch (Specification) presents data as you'd type the commands, while the -L switch (List) displays a logical map of your ip rules.

If you viewed your chains after creating the example chain above in Custom Chain Examples, you would see the primary chains and your custom chains you've created (but you still wouldn't see the routing chains).

iptables -L
Would yield something like this:

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

Chain ICMP-CHAIN (0 reference)
target     prot opt source               destination

How to Delete Chains

Similar to displaying a list of rules, you may delete rules either by Rule Specification or by Chain and Number.

Deleting Rules by Chain and Number

Use the --line-numbers parameter to observe the line numbers of the rules in the appropriate chain.

iptables -L INPUT --line-numbers

Will yield output similar to this:

Chain INPUT (policy DROP)
num target prot opt source destination
1 ACCEPT all -- anywhere anywhere ctstate ESTABLISHED
2 ACCEPT all -- anywhere anywhere
3 DROP all -- anywhere anywhere ctstate INVALID
4 UDP udp -- anywhere anywhere ctstate NEW

Now, to delete a rule you would use the -D command. For example, to delete rule 3 from the INPUT table, you would type:

iptables -D INPUT 3

Deleting Rules by Specification

I personally find it much easier to delete rules by chain and rule number most of the time, but there is another, albeit cumbersome way to do it: contextually, by specifying a specific rule using identical rule text:

iptables -D  [rule syntax]

Such as:

iptables -D INPUT -m conntrack --ctstate INVALID -j REJECT

Flushing Chains (Delete All Rules)

Sometimes you just want to delete all the rules in a chain and start over. There's an easy method of accomplishing this task; the Flush command (-F). Make sure you specify a chain, unless you wish to flush all the chains (see below).

iptables -F {chain}

Such as:

iptables -F INPUT

Flush All Chains

To flush all chains, type:

iptables -F

[1] Quality of Service or QoS refers to a system of network traffic and resource allocations as a mechanism of controlling network traffic prioritization.

[2] James Morris announced the Security table in iptables via a Request For Comment email in January 2008 where he posited moving some marking features of the Mangle table to this new Security table. Thankfully, that never happened as most Linux distributions do not use SELinux, which is required for the Security table to function (Morris, 2008).