Overview
Iptables is a basic firewall tool in Linux and also a very common network tool, but iptables is just an application layer application, so how does iptables relate to the Linux kernel network stack? In this article, I will give a brief introduction about 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.
The following injection points are commonly used.
- 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 have been confirmed as being 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: incoming outgoing traffic created by this machine is executed after it 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
iptables is one of the tools provided by the Linux kernel to the application layer for setting up NetFliter. iptables organizes rules through table
, the so-called table is actually corresponding to different functions, for example
- NAT: Network Address Translation
- Filter: filtering packets
- Mangle: Modify packets (mainly IP Header)
- Raw: modify the original packet
- Security: this is to add SELinux marker to the datagram (generally users are not used)
In each table, iptables organizes the rules by chains, the so-called chains actually correspond to the different Hooks in NetFilter, which actually defines the timing of the execution of the rules in the following order.
iptables chain | NetFilter Hook |
---|---|
PREROUTING | NF_IP_PRE_ROUTING |
INPUT | NF_IP_LOCAL_IN |
FORWARD | NF_IP_FORWARD |
OUTPUT | NF_IP_LOCAL_OUT |
POSTROUTING | NF_IP_POST_ROUTING |
The running 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
Tables↓/Chains→ | PREROUTING | INPUT | FORWARD | OUTPUT | POSTROUTING | |
---|---|---|---|---|---|---|
(routing decision) | ✓ | |||||
raw | ✓ | ✓ | ||||
(connection tracking enabled) | ✓ | ✓ | ||||
mangle | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
nat (DNAT) | ✓ | ✓ | ✓ | |||
(routing decision) | ✓ | ✓ | ||||
filter | ✓ | ✓ | ✓ | ✓ | ||
security | ✓ | ✓ | ✓ | ✓ | ||
nat (SNAT) | ✓ | ✓ |
User-defined chains
For iptables, the so-called rules can be understood as consisting of two parts, namely
- Matching part
- Action part
- The terminating actions: actions that give immediate results, such as the default: ACCEPT, REJECT, etc.
- Non-terminating actions: actions that call another chain until the other chain returns
The so-called custom chain here is 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 work. 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 directly, for example
INPUT_CHAIN_NGINX
: a custom chain for nginxINPUT_CHAIN_ENVOY
: the custom chain for envoy
The actual implementation of custom chains
Because by default, iptables will only use the 5 default chains, custom chains will not be 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
This means adding a reference to 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. Here connection tracing does not only refer to our common TCP connections, but also includes UDP and even ICMP, which are called traceable protocols. These protocols are called traceable protocols and are based on tuples of “connections”, for example, TCP is a quadruple <SrcIP, SrcPORT, DestIP, DestPort>
.
What connection tracing does
Connection tracking is still essentially for packet actions, for example a web host with a firewall set up, if we open the ingress to port 80, it may not be appropriate for the egress to be 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 egress 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.