C++怎么使用libnetfilter_queue在用户态拦截并深度过滤数据包

夏浩小哥_2429

夏浩小哥_2429

2026-11-04

235人浏览

原创

nfq_handle_packet收不到包的主因是iptables规则未正确触发NFQUEUE:需确认规则使用-j NFQUEUE(非已废弃的-j QUEUE)、--queue-num与代码nfq_create_queue绑定的队列号严格一致,且链选择正确(如本机出包用OUTPUT而非POSTROUTING)。

c++怎么使用libnetfilter_queue在用户态拦截并深度过滤数据包

nfq_handle_packet 为什么收不到包?检查 iptables 规则和 queue number 是否匹配

libnetfilter_queue 不是独立工作的,它依赖内核 netfilter 的 QUEUE 目标把包送到用户态。最常见问题是 nfq_handle_packet 长时间阻塞却没数据——大概率是 iptables 没真正把包送进来。

确认点有三个:

  • iptables 必须用 -j NFQUEUE,不能写成 -j QUEUE(后者是旧接口,已废弃)
  • --queue-num 值必须和代码中 nfq_bind_socket 绑定的队列号一致,比如 iptables 用 --queue-num 0,代码里就得调用 nfq_create_queue(h, 0, ...)
  • 确保规则加在正确链上:INPUT/OUTPUT 用于本机进出,FORWARD 用于转发;若想拦截本机发出的 SYN 包,OUTPUT 链比 POSTROUTING 更可靠(后者可能已被连接跟踪模块提前处理)

临时调试可加日志:运行 sudo iptables -I OUTPUT -p tcp --dport 80 -j NFQUEUE --queue-num 0 -m limit --limit 5/sec,避免 flood 导致程序卡死。

如何安全地修改 payload 并重新注入?别直接改 nfq_get_payload 返回的指针

nfq_get_payload 返回的是内核 skb 数据的只读映射,直接写会触发 segfault 或静默失败。真正修改需走「重建 packet」流程。

典型做法是:

  • 用 nfq_get_payload 读出原始数据到用户缓冲区(如 std::vector)
  • 解析 IP/TCP 头(推荐用 libpcap 的 pcap_next_ex 解析逻辑,或手撸偏移计算;注意 IP 总长、TCP 数据偏移、校验和字段都要重算)
  • 修改 payload 后,调用 nfq_set_verdict + nfq_set_payload 注入新数据;注意 nfq_set_payload 第二个参数必须是完整 IP 包(含 IP 头),不能只传 TCP 段
  • 务必重算 IP 校验和(ip_summed = 0)和 TCP 校验和(需伪头+TCP段+data,Linux 内核不帮你算)

漏掉校验和重算,包大概率被接收端丢弃,现象是「看起来发出去了但对方收不到」。

深度过滤时怎么拿到五元组和连接状态?靠 nfq_get_nfmark 和 conntrack 接口协同

libnetfilter_queue 本身不提供连接跟踪信息。要判断 SYN/FIN/RST、是否属于已有连接、NAT 后的地址,得结合 libnetfilter_conntrack。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

操作路径是:

  • 先用 nfq_get_nfmark 获取包的 nfmark 值(如果 iptables 里用了 -j CONNMARK --save-mark)
  • 更可靠的方式:从 nfq_get_payload 解析出源/目的 IP+端口,再用 nfct_query(ct, NFCT_Q_GET, &tuple) 查 conntrack 表;tuple 需按方向填两次(正向+反向)才能准确定位连接
  • 注意 conntrack 查询是阻塞 I/O,高并发下建议用异步方式(如 epoll + nfct_open(0) 创建非阻塞句柄),否则一个慢查询拖垮整个 queue 处理线程

单纯靠包内容判断「是否 HTTPS」容易误判(SNI 在 TLS ClientHello 里,但加密后看不到),此时必须依赖 conntrack 的 orig_l4proto == IPPROTO_TCP && orig_dst_port == 443 这类元数据。

多线程处理 queue 时 nfq_handle_packet 为啥崩溃?libnetfilter_queue 不是线程安全的

所有 struct nfq_handle* 和 struct nfq_q_handle* 对象都绑定到单个线程。多个线程共用同一个 h 调用 nfq_handle_packet 会破坏内部缓冲区,表现是随机 segfault 或 errno = EAGAIN 频发。

正确方案只有两个:

  • 单线程循环调用 nfq_handle_packet,收到包后用线程池处理解析/过滤逻辑,最后仍由主线程调用 nfq_set_verdict(因为 verdict 必须在原 socket 上回复)
  • 开多个 queue(iptables 用不同 --queue-num),每个 queue 绑定独立 nfq_handle 和独立线程;但要注意 CPU 亲和性——同一连接的包可能被 hash 到不同 queue,导致状态不一致

没有「线程安全的 queue handler」这种东西,文档里明确写了「not thread-safe」,别试图加 mutex 绕过。

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++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习