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 → natINPUT: mangle → filter → securityFORWARD: mangle → filter → securityOUTPUT: raw → mangle → nat → filter → securityPOSTROUTING: 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.cPOSTROUTING 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.hSNAT 实现
源码位置:
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# 测试 SSHssh user@server# 测试 HTTPcurl http://server# 测试被拒绝的端口telnet server 8080# 应该被拒绝案例 2:配置 NAT 网关
需求:
-
内网:192.168.1.0/24
-
外网接口:eth0
-
内网接口:eth1
-
实现内网访问外网(SNAT)
-
实现端口转发(DNAT)
实现:

验证:
# 在内网主机测试外网访问ping 8.8.8.8curl http://www.google.com# 在外网测试端口转发curl http://外网IP:80 # 应该访问到 192.168.1.100curl 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 的配合
性能优化建议
-
连接跟踪优化:增大表大小,调整超时时间
-
规则优化:常用规则前置,使用 ipset
-
硬件卸载:利用网卡硬件加速
-
使用 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=20000002. 减少超时:sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=6003. 清理无效连接:conntrack -D-p tcp --state TIME_WAIT# 长期解决1. 对高流量端口禁用连接跟踪(raw 表 NOTRACK)2. 使用硬件卸载3. 优化应用层,减少连接数Q3:如何调试 iptables 规则?
A:
# 1. 查看规则匹配计数iptables -L -n -v# 2. 添加日志规则iptables -I INPUT 1 -j LOG --log-prefix "DEBUG: "# 3. 使用 TRACE 目标(需要加载 xt_TRACE 模块)modprobe ipt_LOGiptables -t raw -A PREROUTING -p tcp --dport 80 -j TRACEiptables -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 iptablesman 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:ipipset create whitelist hash:net# 添加元素ipset add blacklist 1.2.3.4ipset add whitelist 192.168.1.0/24# 删除元素ipset del blacklist 1.2.3.4# 查看集合ipset listipset list blacklist# 测试元素ipset test blacklist 1.2.3.4# 保存和恢复ipset save > /etc/ipset.confipset restore < /etc/ipset.conf# 在 iptables 中使用iptables -A INPUT -m set --match-set blacklist src -j DROPnftables 常用命令:
# 查看规则nft list rulesetnft list table inet filternft list chain inet filter input# 添加表和链nft add table inet filternft add chain inet filter input { type filter hook input priority 0 \; }# 添加规则nft add rule inet filter input tcp dport 80 acceptnft insert rule inet filter input position 0 tcp dport 22 accept# 删除规则nft delete rule inet filter input handle 5# 清空规则nft flush table inet filternft flush chain inet filter input# 保存和恢复nft list ruleset > /etc/nftables.confnft -f /etc/nftables.conf
作者:肇中
夜雨聆风





































