C++ 怎么在 Linux 内核中使用 Netfilter 框架修改和重定向 TCP/IP 数据包

胖伟酱_6531

胖伟酱_6531

2026-11-02

226人浏览

原创

Linux内核模块重定向TCP包需在netfilter hook中修改skb字段并处理conntrack:先校验协议、调用skb_make_writable(),更新IP头TTL和TCP校验和,再清理或绕过conntrack状态,否则连接会卡在SYN_SENT或无ACK。

c++ 怎么在 linux 内核中使用 netfilter 框架修改和重定向 tcp/ip 数据包

Linux 内核模块中注册 netfilter hook 处理 TCP 包

不能在内核模块里直接调用用户态的 libnetfilter_queue 或 iptables 命令——那些是用户空间机制。真正修改/重定向数据包,必须在内核态注册 nf_hook_ops,挂载到 NF_INET_PRE_ROUTING 或 NF_INET_LOCAL_OUT 等关键点。

常见错误是 hook 函数返回值写错:NF_ACCEPT 表示放行、NF_DROP 丢弃、NF_STOLEN 表示已接管(不再走后续流程)、NF_QUEUE 是交给用户态队列(需配合 nfnetlink_queue 模块)。TCP 包重定向通常要改 sk_buff->ip_hdr()->daddr 和 tcp_hdr()->dest,但必须先调用 skb_make_writable(),否则可能因分页或共享缓冲区导致崩溃。

  • 务必检查 skb->protocol == htons(ETH_P_IP) 且 ip_hdr(skb)->protocol == IPPROTO_TCP
  • 修改 IP 头前用 ip_decrease_ttl(ip_hdr(skb)) 更新 TTL,否则可能被中间设备丢弃
  • 若修改目的端口,需同步更新 TCP 校验和:调用 tcp_v4_csum_init(skb) 或手动重算 tcp_hdr(skb)->check = 0; tcp_hdr(skb)->check = tcp_v4_checksum(skb);

重定向 TCP 连接时绕过 conntrack 的坑

内核默认启用 nf_conntrack,一旦你修改了目的 IP/端口,conntrack 会认为这是新连接,原连接状态丢失,ACK 包可能被拒绝或无法回包。最直接的规避方式是在 hook 函数中调用 nf_ct_destroy(ct) 主动销毁旧连接跟踪项,或在模块初始化时通过 nf_ct_netns_get() 获取对应 netns 的 conntrack 表并清理匹配项。

更稳妥的做法是:在 NF_INET_PRE_ROUTING 中重定向后,立即在 NF_INET_POST_ROUTING 中对返回包做反向 DNAT,保持连接对称。但这要求你能在两个 hook 间传递标识信息——可用 skb->mark 或自定义 skb_ext 存储原始目的地址,避免依赖 conntrack 状态。

  • 不要在 NF_INET_LOCAL_OUT 中只改 dst 而不 touch conntrack:本地发起的 TCP 连接会卡在 SYN_SENT,因为 reply 包找不到匹配的 conntrack entry
  • nf_conntrack_tcp_be_liberal = 1 可缓解部分乱序/校验问题,但不解决重定向后的状态不一致
  • 使用 nf_ct_delete() 前确认 ct != NULL,否则 oops

编译和加载 netfilter 内核模块的最小依赖

内核配置必须开启:CONFIG_NETFILTER=y、CONFIG_NETFILTER_ADVANCED=y、CONFIG_NF_CONNTRACK=m(如果要用 conntrack)、CONFIG_IP_NF_IPTABLES=m(非必须,但调试时方便用 iptables -j NFLOG 配合 dmesg 查看流量路径)。

Linux Security Scanner
Linux Security Scanner

Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...

下载

Makefile 必须显式链接 net 和 nf_conntrack(如果用了):

obj-m += my_nf_redirect.o
my_nf_redirect-objs := nf_redirect_main.o nf_redirect_hook.o
KDIR := /lib/modules/$(shell uname -r)/build
all:
	make -C $(KDIR) M=$(PWD) modules

加载前检查依赖模块是否已载入:lsmod | grep -E 'nf_conntrack|nf_defrag_ipv4|nf_nat'。缺 nf_defrag_ipv4 会导致 IPv4 分片包无法重组,hook 收到的可能是不完整的 TCP 包。

  • 模块中不能使用 printk 输出大量日志——TCP 高频场景下极易引发 soft lockup
  • 所有内存分配优先用 kmalloc(..., GFP_ATOMIC),不能在 hook 中 sleep
  • 修改 sk_buff 后建议调用 skb_clear_hash(skb),防止路由缓存误判

调试 TCP 重定向失败的关键信号

最常遇到的是“包发出去了,但没收到 ACK”或“连接超时”。先确认是否真进了你的 hook:dmesg -w 看是否有你写的 printk;再用 tcpdump -i any port XXX 对比进出接口的包内容,重点看 IP 头目的地址、TCP 端口、SYN/FIN 标志位是否符合预期。

若发现重定向后的包 TTL=1 或 checksum 错误,说明没调 ip_decrease_ttl() 或没重算 TCP 校验和;若只有第一次 SYN 能发出去,后续 ACK 不见,则大概率是 conntrack 干扰,此时执行 echo 0 > /proc/sys/net/netfilter/nf_conntrack_tcp_be_liberal 并清空表:conntrack -F(仅测试环境)。

  • cat /proc/net/nf_conntrack | grep :XXXX 查看对应端口的连接状态,观察 src/dst 是否被你改写后仍被正确跟踪
  • 用 iptables -t raw -A OUTPUT -p tcp --dport YYYY -j TRACE 触发内核 trace,配合 sudo cat /sys/kernel/debug/tracing/trace_pipe 定位 hook 执行位置
  • 不要依赖 skb->dev 判断方向——在 LOCAL_OUT 中它可能是 loopback,在 PRE_ROUTING 中可能是 eth0,应以 skb->skb_iif 和网络命名空间上下文为准

实际写的时候,最难的不是改几个字段,而是让整个网络栈相信这个包“本该如此”。哪怕一个 TTL 没减、一个校验和没重算、一个 conntrack entry 没清理,都可能让 TCP 连接卡在三次握手半途中,而错误现象看起来跟网络不通一模一样。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2288

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

1039

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

447

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

347

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

426

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

600

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1429

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1237

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ 手册教程
C++ 手册教程

共41课时 | 78.6万人学习

Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习

Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习