乐于分享
好东西不私藏

Linux 网络子系统源码剖析(九):Netfilter 与 iptables 源码解析

Linux 网络子系统源码剖析(九):Netfilter 与 iptables 源码解析

从数据包过滤到 NAT – 揭秘 Linux 防火墙的实现机制

系列:Linux 网络子系统源码剖析篇号:第 9 篇    内核版本:Linux 5.10 LTS重点模块:Netfilter 框架、iptables、连接跟踪、NAT


📋 本篇导读

你将学到

  • Netfilter 框架的完整架构

  • 五个 Hook 点的实现原理

  • iptables 规则管理机制

  • 连接跟踪(conntrack)的实现

  • NAT(网络地址转换)的源码分析

  • 性能优化技巧

  • 实战案例与问题排查

前置知识

  • 已阅读第 1-8 篇文章

  • 了解 TCP/IP 协议栈

  • 熟悉 iptables 基本使用

  • 理解网络数据包处理流程

阅读时间

约 90-100 分钟


🎯 Netfilter 在网络子系统中的位置

协议栈分层

Netfilter 的核心职责


📊 数据包处理流程

完整的数据包流转路径

表和链的优先级

PREROUTING:  raw → mangle → nat
INPUT:       mangle → filter → security
FORWARD:     mangle → filter → security
OUTPUT:      raw → mangle → nat → filter → security
POSTROUTING: mangle → nat

🏗️ Netfilter 框架架构

核心概念

Netfilter 是 Linux 内核中的网络包过滤框架,提供了包过滤、NAT、连接跟踪等功能。iptables 是用户空间的配置工具,用于管理 Netfilter 规则。

表(Table)

  • filter:包过滤(默认表)

  • nat:网络地址转换

  • mangle:包修改

  • raw:连接跟踪豁免

  • security:SELinux 相关

链(Chain)

  • PREROUTING:路由前

  • INPUT:进入本机

  • FORWARD:转发

  • OUTPUT:本机发出

  • POSTROUTING:路由后

目标(Target)

  • ACCEPT:接受数据包

  • DROP:丢弃数据包

  • REJECT:拒绝并返回错误

  • SNAT:源地址转换

  • DNAT:目的地址转换

  • MASQUERADE:动态 SNAT

  • LOG:记录日志

核心数据结构

源码位置include/linux/netfilter.h



🔗 五个 Hook 点实现

Hook 点概览

Netfilter 在数据包处理的关键位置设置了 5 个 Hook 点,每个 Hook 点可以注册多个处理函数。

PREROUTING Hook

在路由判断之前执行,用于 DNAT 和连接跟踪。

源码位置net/ipv4/ip_input.c

/**
* ip_rcv - IP 层接收入口
* @skb: 数据包
* @dev: 网络设备
* @pt: 协议类型
* @orig_dev: 原始设备
* 处理接收到的 IP 数据包
*/

/**
* ip_rcv_finish - PREROUTING 后的处理
* @net: 网络命名空间
* @sk: Socket
* @skb: 数据包
* PREROUTING hook 执行完成后调用
*/

INPUT Hook

数据包进入本机时执行,用于本地防火墙。

源码位置net/ipv4/ip_input.c


/**
* ip_local_deliver_finish - INPUT 后的处理
* @net: 网络命名空间
* @sk: Socket
* @skb: 数据包
* 将数据包交付给上层协议
*/

FORWARD Hook

数据包转发时执行,用于路由器防火墙。

源码位置net/ipv4/ip_forward.c

/**
* ip_forward - IP 转发
* @skb: 数据包
* 转发数据包到其他主机
*/

/**
* ip_forward_finish - FORWARD 后的处理
* @net: 网络命名空间
* @sk: Socket
* @skb: 数据包
*/

OUTPUT Hook

本机发出数据包时执行,用于本地出站过滤。

源码位置net/ipv4/ip_output.c

POSTROUTING Hook

路由后执行,用于 SNAT 和 MASQUERADE。

/**
* ip_finish_output - 完成 IP 输出
* @net: 网络命名空间
* @sk: Socket
* @skb: 数据包
* POSTROUTING hook 执行完成后调用
*/

/**
* ip_finish_output2 - 完成 IP 输出(第二阶段)
* @net: 网络命名空间
* @sk: Socket
* @skb: 数据包
* 通过邻居子系统发送数据包
*/

🎣 Hook 注册和执行

Hook 注册机制

源码位置net/netfilter/core.c

/**
* nf_register_net_hook - 注册 Netfilter hook
* @net: 网络命名空间
* @reg: hook 操作结构
* 将 hook 函数注册到指定的 hook 点
*/

/**
* nf_unregister_net_hook - 注销 Netfilter hook
* @net: 网络命名空间
* @reg: hook 操作结构
*/

Hook 执行流程

/**
* nf_hook_slow - 执行 Netfilter hook 链
* @skb: 数据包
* @state: Hook 状态
* @e: Hook 入口
* @i: 起始索引
* 遍历 hook 链,依次执行每个 hook 函数
*/

/**
* NF_HOOK - Netfilter hook 宏
* @pf: 协议族
* @hook: Hook 点
* @net: 网络命名空间
* @sk: Socket
* @skb: 数据包
* @in: 入接口
* @out: 出接口
* @okfn: 成功后的回调函数
* 在指定的 hook 点执行 hook 链
*/

Hook 执行流程图



📋 iptables 规则管理

iptables 表结构

源码位置net/ipv4/netfilter/ip_tables.c

规则匹配流程

/**
* ipt_do_table - 执行 iptables 规则匹配
* @skb: 数据包
* @state: Hook 状态
* @table: iptables 表
* 遍历规则链,匹配并执行规则
*/

规则匹配流程图


🔍 连接跟踪(conntrack)

连接跟踪是 Netfilter 的核心功能,用于跟踪网络连接状态,支持状态防火墙和 NAT。

连接跟踪数据结构

源码位置include/net/netfilter/nf_conntrack.h

连接跟踪流程

源码位置net/netfilter/nf_conntrack_core.c

/**
* nf_conntrack_in - 连接跟踪入口
* @skb: 数据包
* @state: Hook 状态
* 处理数据包的连接跟踪
*/

连接跟踪状态转换

NEW          → ESTABLISHED  (收到回复)
ESTABLISHED  → FIN_WAIT     (收到 FIN)
FIN_WAIT     → CLOSE        (收到 FIN+ACK)

使用连接跟踪的 iptables 规则


🔄 NAT 实现

NAT (Network Address Translation) 用于修改数据包的源或目的地址。

NAT 数据结构

源码位置include/net/netfilter/nf_nat.h

SNAT 实现

源码位置net/netfilter/nf_nat_core.c

/**
* nf_nat_packet - 执行 NAT
* @ct: 连接跟踪条目
* @ctinfo: 连接信息
* @hooknum: Hook 点
* @skb: 数据包
* 根据连接跟踪信息修改数据包
*/

NAT 配置示例


⚡ 性能优化

连接跟踪优化

iptables 规则优化

1. 规则顺序优化

2. 使用 ipset

3. 使用 nftables

nftables 是 iptables 的替代品,性能更好。

硬件卸载

现代网卡支持连接跟踪硬件卸载,大幅提升性能。

# 查看网卡是否支持硬件卸载
ethtool -k eth0 | grep hw-tc-offload

# 启用硬件卸载
ethtool -K eth0 hw-tc-offload on

# 查看卸载的连接
cat /proc/net/nf_conntrack | grep OFFLOAD

性能对比

场景:100 万并发连接

软件连接跟踪:
- CPU 使用率:80%
- 吞吐量:10 Gbps
- 延迟:1-2 ms

硬件卸载:
- CPU 使用率:20%
- 吞吐量:40 Gbps
- 延迟:0.1-0.2 ms

💼 实战案例

案例 1:构建基本防火墙

需求

  • 允许 SSH(22)、HTTP(80)、HTTPS(443)

  • 允许已建立的连接

  • 拒绝其他所有入站连接

  • 允许所有出站连接

实现

验证

# 查看规则
iptables -L -n -v

# 测试 SSH
ssh user@server

# 测试 HTTP
curl http://server

# 测试被拒绝的端口
telnet server 8080# 应该被拒绝

案例 2:配置 NAT 网关

需求

  • 内网:192.168.1.0/24

  • 外网接口:eth0

  • 内网接口:eth1

  • 实现内网访问外网(SNAT)

  • 实现端口转发(DNAT)

实现

验证

# 在内网主机测试外网访问
ping 8.8.8.8
curl http://www.google.com

# 在外网测试端口转发
curl http://外网IP:80      # 应该访问到 192.168.1.100
curl http://外网IP:8080    # 应该访问到 192.168.1.101

# 查看 NAT 连接
cat /proc/net/nf_conntrack | grep-E"192.168.1"

案例 3:防御 DDoS 攻击

需求

  • 限制连接速率

  • 防御 SYN Flood

  • 防御 UDP Flood

  • 防御 ICMP Flood

实现

监控脚本

案例 4:排查连接跟踪问题

问题现象

  • 连接超时

  • 日志显示 “nf_conntrack: table full”

  • 新连接无法建立

排查步骤

解决方案


📝 总结

本文深入剖析了 Netfilter 和 iptables 的实现机制。

核心要点

Netfilter 框架

  • 五个 Hook 点:PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING

  • Hook 注册和执行机制

  • 按优先级排序的 Hook 链

iptables 规则

  • 四表五链结构

  • 规则匹配流程:遍历规则链,依次匹配

  • 目标动作:ACCEPT、DROP、REJECT、SNAT、DNAT 等

连接跟踪

  • 五元组标识连接

  • 连接状态:NEW、ESTABLISHED、RELATED、INVALID

  • TCP 状态机跟踪

  • 超时管理

NAT 实现

  • SNAT:修改源地址和端口

  • DNAT:修改目的地址和端口

  • MASQUERADE:动态 SNAT

  • 连接跟踪与 NAT 的配合

性能优化建议

  1. 连接跟踪优化:增大表大小,调整超时时间

  2. 规则优化:常用规则前置,使用 ipset

  3. 硬件卸载:利用网卡硬件加速

  4. 使用 nftables:替代 iptables,性能更好

下一篇预告

下一篇《流量控制(QoS)源码解析》将深入分析:

  • Linux 流量控制框架

  • 队列规则(qdisc)实现

  • 分类器(classifier)机制

  • 常用 QoS 算法(HTB、TBF、SFQ)

  • 流量整形实战


❓ 常见问题(FAQ)

Q1:iptables 和 nftables 有什么区别?

A:

  • iptables:传统工具,规则匹配线性遍历,性能较低

  • nftables:新一代工具,使用虚拟机执行规则,性能更高

  • nftables 统一了 iptables、ip6tables、arptables、ebtables

  • 建议新系统使用 nftables

Q2:连接跟踪表满了怎么办?

A:

# 临时解决
1. 增大表大小:sysctl -w net.netfilter.nf_conntrack_max=2000000
2. 减少超时:sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=600
3. 清理无效连接:conntrack -D-p tcp --state TIME_WAIT

# 长期解决
1. 对高流量端口禁用连接跟踪(raw 表 NOTRACK)
2. 使用硬件卸载
3. 优化应用层,减少连接数

Q3:如何调试 iptables 规则?

A:

# 1. 查看规则匹配计数
iptables  -L -n -v

# 2. 添加日志规则
iptables  -I INPUT -j LOG --log-prefix "DEBUG: "

# 3. 使用 TRACE 目标(需要加载 xt_TRACE 模块)
modprobe ipt_LOG
iptables  -t raw -A PREROUTING -p tcp --dport 80 -j TRACE
iptables  -t raw -A OUTPUT -p tcp --sport 80 -j TRACE

# 4. 查看日志
tail -f /var/log/kern.log | grep TRACE

# 5. 使用 tcpdump 抓包
tcpdump -i any  -nn 'tcp port 80'

Q4:SNAT 和 MASQUERADE 有什么区别?

A:

  • SNAT:指定固定的源地址,适用于静态 IP

  • MASQUERADE:动态获取源地址,适用于动态 IP(如 PPPoE、DHCP)

  • MASQUERADE 性能略低(需要查询接口 IP)

  • 示例:

    
    

Q5:如何限制单个 IP 的连接数?

A:

Q6:如何查看某个连接的 NAT 信息?

A:

# 查看所有连接
cat /proc/net/nf_conntrack

# 查看特定 IP 的连接
cat /proc/net/nf_conntrack | grep 192.168.1.100

# 使用 conntrack 工具
conntrack -L | grep 192.168.1.100

# 查看 NAT 映射
conntrack -L -p tcp --dport 80 | grep SNAT

📚 参考资料

内核源码

  • net/netfilter/core.c – Netfilter 核心框架

  • net/netfilter/nf_conntrack_core.c – 连接跟踪核心

  • net/netfilter/nf_conntrack_proto_tcp.c – TCP 连接跟踪

  • net/netfilter/nf_nat_core.c – NAT 核心实现

  • net/ipv4/netfilter/ip_tables.c – iptables 实现

  • net/ipv4/netfilter/iptable_filter.c – filter 表

  • net/ipv4/netfilter/iptable_nat.c – nat 表

  • net/ipv4/netfilter/nf_nat_l3proto_ipv4.c – IPv4 NAT

  • net/netfilter/xt_conntrack.c – conntrack 匹配器

  • net/netfilter/xt_state.c – state 匹配器

用户空间工具

  • iptables – 规则管理工具

  • nftables – 新一代规则管理工具

  • conntrack-tools – 连接跟踪工具

  • ipset – IP 集合管理工具

文档和手册

# iptables 手册
man iptables
man iptables-extensions

# nftables 手册
man nft

# conntrack 手册
man conntrack

# 内核文档
/usr/src/linux/Documentation/networking/nf_conntrack-sysctl.txt

在线资源

  • Netfilter 官网:https://www.netfilter.org/

  • iptables 教程:https://www.frozentux.net/iptables-tutorial/

  • nftables Wiki:https://wiki.nftables.org/

  • Linux 内核文档:https://www.kernel.org/doc/html/latest/networking/

书籍推荐

  • 《Linux 防火墙》- Steve Suehring

  • 《深入理解 Linux 网络技术内幕》- Christian Benvenuti

  • 《Linux 内核源代码情景分析》- 毛德操、胡希明

实用命令速查

iptables 常用命令

conntrack 常用命令

# 查看连接
conntrack -L# 列出所有连接
conntrack -L -p tcp                  # 列出 TCP 连接
conntrack -L -p tcp --dport 80# 列出特定端口

# 删除连接
conntrack -D -p tcp --dport 80# 删除特定连接
conntrack -D -p tcp --state TIME_WAIT # 删除特定状态

# 统计信息
conntrack -S# 显示统计信息
conntrack -C# 显示连接数

# 监控连接
conntrack -E# 实时监控连接事件

ipset 常用命令

# 创建集合
ipset create blacklist hash:ip
ipset create whitelist hash:net

# 添加元素
ipset add blacklist 1.2.3.4
ipset add whitelist 192.168.1.0/24

# 删除元素
ipset del blacklist 1.2.3.4

# 查看集合
ipset list
ipset list blacklist

# 测试元素
ipset test blacklist 1.2.3.4

# 保存和恢复
ipset save > /etc/ipset.conf
ipset restore < /etc/ipset.conf

# 在 iptables 中使用
iptables -A INPUT -m set --match-set blacklist src -j DROP

nftables 常用命令

# 查看规则
nft list ruleset
nft list table inet filter
nft list chain inet filter input

# 添加表和链
nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; }

# 添加规则
nft add rule inet filter input tcp dport 80 accept
nft insert rule inet filter input position 0 tcp dport 22 accept

# 删除规则
nft delete rule inet filter input handle 5

# 清空规则
nft flush table inet filter
nft flush chain inet filter input

# 保存和恢复
nft list ruleset > /etc/nftables.conf
nft -f /etc/nftables.conf

作者:肇中