iptables is a basic firewall tool in Linux, and also a very common network workhorse, but iptables is really only an application layer, so how does iptables relate to the Linux kernel network stack, here I will give a brief introduction to this issue.

NetFilter framework

The Netfilter framework is a framework provided by the Linux kernel network for applications to register various Handlers, allowing users to control parts of the Linux network through the Netfilter framework.

Commonly used injection points are the following.

  • NF_IP_PRE_ROUTING: called as soon as a packet enters the network stack, without any network decisions being executed.
  • NF_IP_LOCAL_IN: incoming packets are executed after they are confirmed to be addressed to this system.
  • NF_IP_FORWARD: incoming packets are executed after they are confirmed to have been sent to another host.
  • NF_IP_LOCAL_OUT: executed after the outgoing traffic created by this machine enters the network stack.
  • NF_IP_POST_ROUTING: executed after outgoing traffic (both locally generated and forwarded) has been routed (before being placed on the NIC).


iptables is one of the tools provided by the Linux kernel to the application layer for setting up NetFliter. iptables organizes rules by table, the so-called table is actually corresponding to different functions, for example

  • NAT: Network Address Translation
  • Filter: filter packets
  • Mangle: Modify packets (mainly IP Header)
  • Raw: modify the original packet
  • Security: this is to add SELinux markers to datagrams (generally not used by users)

In each table, iptables organizes rules by chains, the so-called chains actually correspond to the different Hooks in NetFilter, which actually defines the order of the timing of the execution of the rules.

iptables Chain NetFilter Hook

The order of table

Because table is a concept only available in iptables, when different tables contain the same chain of rules, there is an order in NetFilter, which cannot be specified by the user.

  • The main chain is from left to right.
    • PreRouting -> Input -> Output -> PostRouting
    • PreRouting -> Forward -> PostRouting
  • For each chain, the execution order goes from top to bottom
(routing decision)
(connection tracking enabled)
nat (DNAT)
(routing decision)
nat (SNAT)

User-defined chains

For iptables, the so-called rules can be understood as consisting of two parts, namely

  • the match part
  • Action part
    • Ending actions: actions that give immediate results, such as the default : ACCEPT, REJECT, etc.
    • Non-terminating actions: actions that invoke another chain until the other chain returns

The so-called custom chain here is the non-terminating action, so why introduce a custom chain?

Introducing custom chains

As said before, the default iptables only has 5 chains, although iptables uses tables to differentiate, but, still not enough, especially in enterprise use (such as Istio), often create a large number of rules, then when I want to check the rules of a certain function, it may not be easy to find, so this custom chain can be useful. We can put the rules for different applications/functions into separate chains, so that when we need to modify or view them we can just look at the corresponding chain, for example

  • INPUT_CHAIN_NGINX : indicates a custom chain for nginx
  • INPUT_CHAIN_ENVOY : indicates a custom chain for envoy

Actual execution of custom chains

Since by default iptables will only use the 5 default chains, the custom chains are not executed. If you want to execute a custom chain, you need to actively call the custom chain (the so-called non-terminating action) in the default chain, so that it works with the custom chain. An example.

[root@liqiang.io]# iptables -I INPUT -p tcp --dport 9090 -j INPUT_CHAIN_ENVOY

It means adding a reference of INPUT_CHAIN_ENVOY to the INPUT chain, and when the INPUT chain is executed, this custom chain will be executed accordingly. The order of the other chains will be executed in the order of the previous table, and the order in the INPUT chain will be executed in the order of your definition from old to new, with the old definition executed first and then the new one.

Connection tracking

iptables also performs connection tracing, which is also based on NetFilter. The connection tracing here does not only refer to our common TCP connections, but also includes UDP and even ICMP, which are all called traceable protocols.

What connection tracing does

For example, if a web host is set up with a firewall, if we open the ingress on port 80, it may not be appropriate to have the egress fully open or fully closed. So can we do half open and half closed, how half open and half closed this is the function of connection tracking, imagine we want to open to whom? We want to be open to clients that have accessed our port 80, so here we can first track the information of clients that have successfully accessed port 80, and then define an exit rule for connections that have been opened.

[root@liqiang.io]# iptables -A OUTPUT -m state --state NEW,RELATED -j ALLOW

This eliminates the need to target specific clients to open egress traffic.