在Linux网络数据包的接收过程和数据包的发送过程两篇文章介绍数据包收发流程中, 已经提到了在内核协议栈处理包过程中在不同阶段提供了不同的hook点,在hook点上可以注册函数来自定义包处理逻辑,内核提供的这些hook点便是众多linux防火墙软件的基础。
在 Linux 生态系统中,iptables 是使用很广泛的防火墙工具之一,它基于内核的包过滤框架(packet filtering framework) netfilter。
netfilter最早是社区开发的防火墙框架,在内核2.4.x版本之后合并入了内核。
netfilter和iptables的关系可以简单理解为:
- netfilter是内核态的包过滤框架。
- iptables是用户态下操作包过滤规则的工具。
netfilter
netfilter 提供了 5 个 hook 点。包经过协议栈时会触发内核模块注册在这里的处理函数 。触发哪个 hook 取决于包的方向(是发送还是接收)、包的目的地址、以及包在上一个 hook 点是被丢弃还是拒绝等等。
- NF_IP_PRE_ROUTING: 接收到的包进入协议栈后立即触发此 hook,在进行任何路由判断 (将包发往哪里)之前
- NF_IP_LOCAL_IN: 接收到的包经过路由判断,如果目的是本机,将触发此 hook
- NF_IP_FORWARD: 接收到的包经过路由判断,如果目的是其他机器,将触发此 hook
- NF_IP_LOCAL_OUT: 本机产生的准备发送的包,在进入协议栈后立即触发此 hook
- NF_IP_POST_ROUTING: 本机产生的准备发送的包或者转发的包,在经过路由判断之后, 将触发此 hook
iptables
iptables 使用 table 来组织规则,根据用来做什么类型的判断(the type of decisions they are used to make)标准,将规则分为不同 table。例如,如果规则是处理 网络地址转换的,那会放到 nat table;如果是判断是否允许包继续向前,那可能会放到 filter table。
在每个 table 内部,规则被进一步组织成 chain,内置的 chain 是由内置的 hook 触发 的。chain 基本上能决定(basically determin)规则何时被匹配。
- PREROUTING: 由 NF_IP_PRE_ROUTING hook 触发
- INPUT: 由 NF_IP_LOCAL_IN hook 触发
- FORWARD: 由 NF_IP_FORWARD hook 触发
- OUTPUT: 由 NF_IP_LOCAL_OUT hook 触发
- POSTROUTING: 由 NF_IP_POST_ROUTING hook 触发
先来看看 iptables 提供的 table 类型。这些 table 是按规则类型区分的。
- filter table 是最常用的 table 之一,用于判断是否允许一个包通过
- nat table 用于实现网络地址转换规则。
- mangle (修正)table 用于修改包的 IP 头。
- raw table 定义的功能非常有限,目前其唯一目的就是提供一个让包绕过连接跟踪的框架。
- security table 的作用是给包打上 SELinux 标记。
连接跟踪
连接跟踪是许多网络应用的基础。例如,Kubernetes Service、ServiceMesh sidecar、 软件四层负载均衡器 LVS/IPVS、Docker network、OVS、iptables 主机防火墙等等,都依赖连接跟踪功能。
连接跟踪所做的事情就是发现并跟踪这些连接的状态,具体包括:
- 从数据包中提取元组(tuple)信息,辨别数据流(flow)和对应的连接(connection)
- 为所有连接维护一个状态数据库(conntrack table),例如连接的创建时间、发送 包数、发送字节数等等
- 回收过期的连接(GC)
- 为更上层的功能(例如 NAT)提供服务
Linux 的连接跟踪是在 Netfilter 中实现的。