当一个网络包进入一台机器的时候。首先拿下 MAC 头看看,是不是我的。如果是,则拿下 IP 头来。得到目标 IP 之后呢,就开始进行路由判断。在路由判断之前,这个节点我们称为 PREROUTING。如果发现 IP 是我的,包就应该是我的,就发给上面的传输层,这个节点叫作 INPUT。如果发现 IP 不是我的,就需要转发出去,这个节点称为 FORWARD。如果是我的,上层处理完毕后,一般会返回一个处理结果,这个处理结果会发出去,这个节点称为 OUTPUT,无论是 FORWARD 还是 OUTPUT,都是路由判断之后发生的,最后一个节点是 POSTROUTING。

在 Linux 内核中,有一个框架叫 Netfilter。它可以在这些节点插入 hook 函数。这些函数可以截获数据包,对数据包进行干预。例如做一定的修改,然后决策是否接着交给 TCP/IP 协议栈处理;或者可以交回给协议栈,那就是 ACCEPT;或者过滤掉,不再传输,就是 DROP;还有就是 QUEUE,发送给某个用户态进程处理。
一个著名的实现,就是内核模块 ip_tables。它在这五个节点上埋下函数,从而可以根据规则进行包的处理。按功能可分为四大类:连接跟踪(conntrack)、数据包的过滤(filter)、网络地址转换(nat)和数据包的修改(mangle)。其中连接跟踪是基础功能,被其他功能所依赖。其他三个可以实现包的过滤、修改和网络地址转换。
在用户态,还有一个你肯定知道的客户端程序 iptables,用命令行来干预内核的规则。内核的功能对应 iptables 的命令行来讲,就是表和链的概念。

iptables 的表分为四种:raw-->mangle-->nat-->filter。这四个优先级依次降低,raw 不常用,所以主要功能都在其他三种表里实现。每个表可以设置多个链。
filter 表处理过滤功能,主要包含三个链:
nat 表主要是处理网络地址转换,可以进行 Snat(改变数据包的源地址)、Dnat(改变数据包的目标地址),包含三个链:
mangle 表主要是修改数据包,包含:
将 iptables 的表和链加入到上面的过程图中,就形成了下面的图和过程。

类似的规则如下:
此文章为9月Day26学习笔记,内容来源于极客时间《趣谈网络协议》,推荐该课程。