发布时间:2026/6/23 15:59:41
TAP/TUN与自定义网络协议栈
这个文章对TAP/TUN讲的比较清楚https://blog.csdn.net/tjcwt2011/article/details/160653673《深入高可用系统原理与设计》https://www.thebyte.com.cn/network/tuntap.html一、在用户空间实现自定义网络协议栈核心思想内核协议栈是个黑盒——你想改 TCP 拥塞控制算法想试一种新的传输协议以前只能改内核源码、重新编译。TUN/TAP 彻底改变了这件事把协议栈从内核里搬到用户空间用普通程序实现而无需修改一行内核代码。工作原理你的用户态协议栈 ──write──→ /dev/net/tun (TAP设备) │ 内核协议栈收到一个以太网帧 │ 当作从真实网卡收到的一样处理 │ 路由查找 → 可能转发到物理网卡发出 反过来 物理网卡收到包 → 内核协议栈 → 路由判定发往 TAP → 你的程序 read() 收到你的程序既是发送方也是接收方完全控制每个字节怎么处理。典型项目都是真实可跑的项目做了什么用的模式microps轻量级 TCP/IP 协议栈专为学习设计TAPtapip用户态 TCP/IP 实现GitHub 热门TAPlevel-ip完整的用户态协议栈支持 curlTAP以microps为例实际操作流程# 1. 创建 TAP 设备sudoiptuntapadddev tap0 mode tap# 2. 配置 IP让宿主机能访问这个虚拟网络sudoipaddradd10.0.0.1/24 dev tap0 --内核能看到这个地址对microps协议栈而言这是网关IPsudoiplinksetdev tap0 up# 3. 运行你自己写的协议栈sudo./app/tcps-itap0# 启动一个 TCP 服务器# 4. 从另一个终端连接测试telnet10.0.0.28080# 真的能通# 5. Wireshark 抓 tap0看到的就是你协议栈发出的帧为什么这对学习/研究有巨大价值传统方式改内核TUN/TAP 方式改一行代码 → 重新编译内核 → 重启 → test改一行代码 → 重新编译程序 → 重跑 → 立即看到结果崩溃 内核 panic机器挂了崩溃 程序退出宿主机 unaffected无法用 Wireshark 抓中间过程Wireshark 直接抓 TAP 接口每个包都能看只能在自己机器上测可以在任何 Linux 机器上跑零硬件成本一句话TUN/TAP 给了你一个完全隔离、可观测、可随意炸掉重建的网络沙盒。二、流量监控与过滤核心思想所有经过 TUN/TAP 的数据包用户态程序都能原样读到。这意味着你可以看到每个包的完整内容不像 iptables 只能看头部决定放行/丢弃/修改/重定向实现内核做不到的灵活策略两种部署模式模式原理典型工具软件 TAP本文重点创建虚拟接口把特定流量导过去httptap、自研过滤器硬件 Tap物理设备在交换机和设备之间串一个物理 Tap 盒商业网络嗅探方案实战案例httptap —— 监控任意程序的 HTTP/HTTPS 流量这是一个真实项目用法极其简单# 监控 curl 发出的所有 HTTP/HTTPS 请求httptap --curlhttps://example.com# 指定只看 80 和 443 端口httptap--http80,8080--https443,8443-- firefox# 导出为 HAR 文件后续用 Chrome DevTools 分析httptap --dump-har output.har -- your-app它的内部实现就是1. 创建 TUN 设备工作在 L3拿到 IP 包 2. 用户态程序自己实现一个 TCP/IP 栈gvisor 或 handrolled 3. 解析出 HTTP 请求/响应 4. 打印 / 存储 / 转发自定义防火墙策略怎么做逻辑非常直观// 伪代码一个基于 TUN 的用户态防火墙while(1){packetread(tun_fd,buf,sizeof(buf));// 从 TUN 读包if(packet.dst_ip1.2.3.4packet.dst_port443){drop(packet);// 丢包屏蔽这个 IP}elseif(packet.payload_contains(malware)){modify_and_forward(packet);// 修改后转发}else{write(tun_fd,packet,len);// 原样放回内核栈}}能力iptables/nftablesTUN/TAP 用户态基于 IP/端口过滤✅✅基于 payload 内容过滤❌ 做不到✅ 任意正则/字符串匹配修改包内容如重写 Host 头✅ NAT 能做一部分✅ 任意修改看到完整包内容包括 payload❌✅性能极高内核态较低用户态拷贝性能瓶颈在哪怎么优化瓶颈原因优化方案内核↔用户态拷贝每个包都要 copy_to_user / copy_from_user用TPACKET_V3 mmap 零拷贝httptap 就是这么做的用了 1000 大小的缓冲通道用户态协议栈慢自己实现 TCP 比内核慢得多用 gvisor 栈代替手写栈兼容性和性能都更好单线程处理一个 read() 循环扛所有包多线程 缓冲通道httptap 用chan []byte做缓冲一句话总结场景TUN/TAP 解决了什么自定义协议栈不改内核在用户空间造一个完整的 TCP/IP可炸可重建可观测流量监控过滤内核做不到的深度包检测DPI在用户态随便写代价是性能如果你是想学习协议选 TAP microps/tapip零成本开干。如果你是想监控特定应用的流量httptap 这种工具开箱即用。如果你要生产环境的高性能过滤TUN/TAP 不是最佳选择但它是最灵活的起点。microps 例子中tap0和真实物理网卡没有做桥接报文是如何从物理网卡发出去的靠内核路由表不需要 bridge。你的直觉是对的——tap0 和 eth0 之间确实没有二层连接。但它们能通靠的是三层路由不是二层桥接。完整路径长这样以 microps 发起一个到8.8.8.8的包为例microps 写包到 tap0 │ ▼ 内核收到 tap0 的以太网帧目的 MAC 是网关的 MAC │ ▼ 内核查路由表8.8.8.8 不在 10.0.0.0/24 → 走默认网关 │ ▼ 默认网关 192.168.1.1 → 下一跳从 eth0 出去 │ ▼ eth0 发出到达物理交换机 → 互联网反过来也一样互联网回包到达 eth0 │ ▼ 内核查路由表去 10.0.0.0/24 的路由 → 下一跳是 tap0 │ ▼ 包从 tap0 送到 microps 的 read()为什么能通三个关键条件说明✅ tap0 有 IPip addr add 10.0.0.1/24 dev tap0内核认为它是一个真实接口✅ 有默认路由ip route add default via 192.168.1.1 dev eth0告诉内核未知目的地走 eth0✅ ip_forward 开启sysctl net.ipv4.ip_forward1允许内核在接口间转发这就够了。内核根本不关心包是从哪个接口进来的它只查路由表。和 bridge 方案的本质区别microps 方案tun/tap 路由虚拟机方案tap bridge连接方式三层路由二层桥接tap0 有 IP 吗✅ 有10.0.0.1❌ 无eth0 有 IP 吗✅ 有192.168.1.50❌ 无IP 移到 br0 上了包怎么出去内核路由 → eth0bridge 转发 → eth0虚拟机能发 ARP 吗❌ 不能没有二层域✅ 能bridge 模拟真实交换机一句话tap0 不需要和 eth0 桥接因为内核路由表会自动把包从 tap0 导向 eth0。bridge 解决的是二层问题ARP/广播microps 这种场景根本不需要二层三层路由就够了。这其实就是我最早说的tun 只能工作在 L3但 L3 靠 ip_forward 完全可以和物理网卡连通。microps 方案中明明创建的是tap而不是tun为什么说是三层路由呢你这个问题问到点子上了。确实不矛盾但需要把谁在做二层、谁在做三层拆清楚。矛盾在哪你的理解我之前说的TAP 二层设备收发以太网帧这个方案靠三层路由通的→ 既然是二层应该靠 bridge 才对→ 桥接才是二层的事啊看起来矛盾但其实两句话说的是不同层的事。拆开看谁负责哪一层以 microps 发一个包到8.8.8.8为例microps 协议栈用户态 │ │ 1. 自己实现 ARP查到网关 MAC aa:bb:cc:dd:ee:ff │ 2. 自己构造完整以太网帧 │ ┌─────────────────────────────────────┐ │ │ eth_hdr: dstaa:bb:cc:dd:ee:ff │ ← microps 自己填的 MAC 头 │ │ ip_hdr: dst8.8.8.8 │ ← microps 自己实现的 IP 层 │ │ tcp_hdr: dst443 │ ← microps 自己实现的 TCP 层 │ └─────────────────────────────────────┘ │ 3. write() 写到 /dev/net/tap → tap0 │ ▼ 内核协议栈收到 tap0 的以太网帧 │ │ 4. 一看目的 MAC aa:bb:cc:dd:ee:ff网关→ 是给我的 │ 5. 剥掉以太网头拿到 IP 包查路由表 │ 8.8.8.8 不在本地 → 走默认网关从 eth0 出去 │ 6. 重新封装以太网帧dst MAC 真实网关 MACeth0 发出 │ ▼ 物理网卡 → 互联网层级谁在做用什么设备二层MAC/ARPmicrops 自己用户态协议栈TAP 只是个管道透传以太网帧三层IP 路由内核路由表不管包从 tap0 还是 eth0 进来内核都查同一张路由表所以为什么说三层路由因为包从 tap0 出来之后内核的处理方式和从 eth0 收到包完全一样剥二层头 → 查三层路由表 → 从另一个接口发出这就是纯三层路由和 bridge 没有任何关系。那为什么 microps 用 TAP 而不用 TUN这才是关键。如果用 TUNTAPTUN收发的数据完整以太网帧含 MAC 头纯 IP 包无 MAC 头microps 能实现 ARP 吗✅ 能自己构造 MAC 头❌ 不能没有 MAC 头可以填microps 能实现完整 TCP/IP 吗✅ 能从二层到四层全自己来⚠️ 缺二层不完整microps 的目的是实现一个完整的 TCP/IP 协议栈用于学习ARP 是 TCP/IP 的一部分。用 TUN 的话ARP 没地方放协议栈就是残的。所以选 TAP 不是为了桥接而是因为TAP 给了 microps 完整的以太网帧让它能自己实现 ARP、自己填 MAC 头从而拥有一个真正完整的协议栈。至于包出去之后怎么路由那是内核的事和 TAP 是几层设备无关。一句话TAP 是二层设备没错但 microps 用 TAP 不是为了做二层桥接而是为了拿到完整以太网帧来实现自己的 ARP。包出了 TAP 之后内核该查路由查路由该走三层走三层——设备是二层的转发路径是三层的不矛盾。2026-6-22 实践记录1. 创建 TAP 设备sudo ip tuntap add dev tap0 mode tap删除命令sudo ip link delete tap02. 配置 IP让宿主机能访问这个虚拟网络sudo ip addr add 10.0.0.1/24 dev tap0 --内核能看到这个地址对microps协议栈而言这是网关IPsudo ip link set dev tap0 up查看tap0的命令 ip a5: tap0: NO-CARRIER,BROADCAST,MULTICAST,UP mtu 1500 qdisc fq_codel state DOWN group default qlen 1000link/ether 62:7f:34:65:fe:85 brd ff:ff:ff:ff:ff:ffinet 10.0.0.1/24 scope global tap0valid_lft forever preferred_lft foreverinet6 fe80::607f:34ff:fe65:fe85/64 scope linkvalid_lft forever preferred_lft forever3. 编写监听程序#includestdio.h#includestring.h#includeunistd.h#includefcntl.h#includesys/ioctl.h#includelinux/if.h#includelinux/if_tun.h#includenetinet/in.h#includearpa/inet.h#includenetinet/ip.hvoidprint_packet(unsignedchar*buf,intn){if(n14){printf([太短 %d字节]\n,n);return;}unsignedchar*src_macbuf;unsignedchar*dst_macbuf6;uint16_tether_type(buf[12]8)|buf[13];printf(---------- 包 len%d ----------\n,n);printf(以太网头:\n);printf( Dst MAC: %02x:%02x:%02x:%02x:%02x:%02x\n,dst_mac[0],dst_mac[1],dst_mac[2],dst_mac[3],dst_mac[4],dst_mac[5]);printf( Src MAC: %02x:%02x:%02x:%02x:%02x:%02x\n,src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]);printf( Type: 0x%04x ,ether_type);switch(ether_type){case0x0800:printf((IPv4)\n);if(n34){structiphdr*ip(structiphdr*)(buf14);structin_addrs,d;s.s_addrip-saddr;d.s_addrip-daddr;printf( IPv4:\n);printf( Src IP: %s\n,inet_ntoa(s));printf( Dst IP: %s\n,inet_ntoa(d));printf( Proto: %d\n,ip-protocol);}break;case0x0806:printf((ARP)\n);break;case0x86dd:printf((IPv6)\n);break;default:printf((未知)\n);break;}}/* * gcc -o read_tap2 read_tap_2.c * */intmain(){intfdopen(/dev/net/tun,O_RDWR);if(fd0){perror(open);return1;}structifreqifr;memset(ifr,0,sizeof(ifr));ifr.ifr_flagsIFF_TAP|IFF_NO_PI;strncpy(ifr.ifr_name,tap0,IFNAMSIZ);if(ioctl(fd,TUNSETIFF,ifr)0){perror(ioctl);return1;}unsignedcharbuf[2048];while(1){intnread(fd,buf,sizeof(buf));if(n0){perror(read);break;}print_packet(buf,n);}close(fd);return0;}4. 运行1、程序运行后会偶尔收到以太网广播报文2、发ping包或udp包程序会显示不断收到arp请求包。–注意不要给10.0.0.1发包要给10.0.0网段的其它地址发包。原理是报文先到内核协议栈协议栈发现是10.0.0网段就会把报文转发给tap0这个网关。这样我们就读取到这个报文了。ping 10.0.0.10echo “hello123456789” |./busybox nc -u 10.0.0.5 99993、我们代码中目前没有响应arp请求所以就卡在arp这一步了。可以手工增加arp表然后就可以收到ping报文和udp报文了。查看arp表有两个命令 arp 或 ip neigh show 删除arp表中一个ip sudo ip neigh del 10.0.0.10 dev tap0 添加一个ipmac地址随便写一个不冲突的 sudo ip neigh add 10.0.0.10 lladdr 00:00:5e:00:53:01 dev tap0 sudo ip neigh add 10.0.0.5 lladdr 00:00:5e:00:53:02 dev tap0协议17代表udp协议协议1代表icmp协议发upd报文时多发一个字符就看到包len增加1--------- 包 len48 ----------以太网头:Dst MAC: 62:7f:34:65:fe:85Src MAC: 00:00:5e:00:53:01Type: 0x0800 (IPv4)IPv4:Src IP: 10.0.0.1Dst IP: 10.0.0.10Proto: 17---------- 包 len50 ----------以太网头:Dst MAC: 62:7f:34:65:fe:85Src MAC: 00:00:5e:00:53:01Type: 0x0800 (IPv4)IPv4:Src IP: 10.0.0.1Dst IP: 10.0.0.10Proto: 17

相关新闻

江科大PWM笔记:呼吸灯、舵机控制、电机调速
2026/6/23 15:59:41

江科大PWM笔记:呼吸灯、舵机控制、电机调速

*psc预分频器,决定计数脉冲的频率arr自动重装载寄存器,决定了多久是一个周期ccr捕获/比较寄存器,决定占空比cnt计数器寄存器,不能写,只能读1在理解呼吸灯原理之前,先了解一些基本公式:1. 频率公…

阅读更多
告别重复操作!OpenClaw 2.7.9 电脑自动化完整落地实操
2026/6/23 15:59:41

告别重复操作!OpenClaw 2.7.9 电脑自动化完整落地实操

🔍一、前言 OpenClaw 是一款备受追捧的高效本地 AI 自动化工具,支持完全离线运行,不依赖外网连接或云端账号绑定,通过智能 AI 逻辑自主操控各类电脑操作。最新 v2.7.9 版本已内置完整运行环境、配套依赖库及多系统适配配置&#…

阅读更多
2026山东大学软件学院项目实训-宠物情绪识别(七)
2026/6/23 15:59:41

2026山东大学软件学院项目实训-宠物情绪识别(七)

一、本周工作概述本周在完成情绪识别 API 调通的基础上,重点对大模型提示词策略进行了系统性研究和优化。核心工作包括:尝试了5种不同的提示词策略、从多维度进行量化评估对比、选择最优方案并完成代码实现、增加后处理验证和降级策略提升系统鲁棒性。二…

阅读更多
深度度量学习实战指南:BN-Inception模型的迁移学习与特征提取完整教程
2026/6/23 16:59:41

深度度量学习实战指南:BN-Inception模型的迁移学习与特征提取完整教程

深度度量学习实战指南:BN-Inception模型的迁移学习与特征提取完整教程 【免费下载链接】Deep_Metric Deep Metric Learning 项目地址: https://gitcode.com/gh_mirrors/de/Deep_Metric 深度度量学习是计算机视觉领域的核心技术之一,而Deep_Metri…

阅读更多
为什么选择UnrealEngineSkyAtmosphere?对比主流天空渲染方案的优势分析
2026/6/23 16:59:41

为什么选择UnrealEngineSkyAtmosphere?对比主流天空渲染方案的优势分析

为什么选择UnrealEngineSkyAtmosphere?对比主流天空渲染方案的优势分析 【免费下载链接】UnrealEngineSkyAtmosphere Unreal Engine Sky Atmosphere Rendering Technique 项目地址: https://gitcode.com/gh_mirrors/un/UnrealEngineSkyAtmosphere UnrealEngi…

阅读更多
游戏开发教学革命:Unfinished-asteroids如何模拟真实工作环境加速学习
2026/6/23 16:59:41

游戏开发教学革命:Unfinished-asteroids如何模拟真实工作环境加速学习

游戏开发教学革命:Unfinished-asteroids如何模拟真实工作环境加速学习 【免费下载链接】unfinished-asteroids IT STARTS HERE ---> 项目地址: https://gitcode.com/gh_mirrors/un/unfinished-asteroids Unfinished-asteroids是一个创新的游戏开发教学项目…

阅读更多
Medium Editor Markdown快速入门:5分钟实现富文本到Markdown的实时转换
2026/6/23 16:59:41

Medium Editor Markdown快速入门:5分钟实现富文本到Markdown的实时转换

Medium Editor Markdown快速入门:5分钟实现富文本到Markdown的实时转换 【免费下载链接】medium-editor-markdown :pencil: A Medium Editor extension to add markdown support. 项目地址: https://gitcode.com/gh_mirrors/me/medium-editor-markdown 你是否…

阅读更多
DriveAGI性能优化技巧:大规模驾驶视频处理的7个最佳实践
2026/6/23 16:59:41

DriveAGI性能优化技巧:大规模驾驶视频处理的7个最佳实践

DriveAGI性能优化技巧:大规模驾驶视频处理的7个最佳实践 【免费下载链接】DriveAGI [CVPR 2024 Highlight] GenAD: Generalized Predictive Model for Autonomous Driving 项目地址: https://gitcode.com/gh_mirrors/dr/DriveAGI 想要高效处理1700小时的大规…

阅读更多
08 - 组织生命体:AI时代组织管理深度诊断试卷
2026/6/23 15:59:41

08 - 组织生命体:AI时代组织管理深度诊断试卷

你正坐在会议室里,CTO刚刚汇报完大模型部署的进展——效率提升了42%,成本下降了28%。董事会很满意。但你知道一个他们不知道的数字:核心工程师的主动离职率,在过去两个季度里翻了一倍。 离职面谈的最后一句话像一根刺扎在你心里:“公司越来越像一台完美的机器,而我越来越…

阅读更多
嵌入式语音编解码实战:G.726 ADPCM库集成与优化指南
2026/6/23 3:25:21

嵌入式语音编解码实战:G.726 ADPCM库集成与优化指南

1. 项目概述与G.726 ADPCM技术背景在嵌入式语音处理领域,带宽和存储资源往往是寸土寸金的。如果你做过对讲机、VoIP网关或者早期的数字录音设备,一定对如何在有限的比特率下保住语音可懂度这件事深有感触。我当年接手一个车载调度系统的项目,…

阅读更多
ITU656格式化器寄存器配置实战:VBI数据处理与VCR特技播放兼容性
2026/6/23 4:51:28

ITU656格式化器寄存器配置实战:VBI数据处理与VCR特技播放兼容性

1. 项目概述与核心挑战在数字视频处理领域,将原始的视频数据、同步时序以及各种辅助信息打包成一个标准、稳定的串行数据流,是确保设备间互联互通的基础。ITU-R BT.656标准(常简称为ITU656)正是为此而生的一套“交通规则”。它定义…

阅读更多
嵌入式GUI开发实战:emWin环境搭建、配置优化与性能调优指南
2026/6/23 0:40:11

嵌入式GUI开发实战:emWin环境搭建、配置优化与性能调优指南

1. 项目概述与emWin核心价值解析在嵌入式系统开发领域,人机交互(HMI)的设计正从简单的LED指示灯和按键,快速向全彩图形化界面演进。无论是智能家电上的触摸屏、工业PLC的操作面板,还是医疗设备的参数显示,一…

阅读更多
3分钟快速上手:Qwen3大语言模型本地部署完全指南
2026/6/23 0:59:31

3分钟快速上手:Qwen3大语言模型本地部署完全指南

3分钟快速上手:Qwen3大语言模型本地部署完全指南 【免费下载链接】Qwen1.5 Qwen3 is the large language model series developed by Qwen team, Alibaba Cloud. 项目地址: https://gitcode.com/GitHub_Trending/qw/Qwen1.5 阿里巴巴Qwen3大语言模型系列以其…

阅读更多
微信聊天记录备份指南:使用WeChatExporter轻松保存您的珍贵回忆
2026/6/23 0:59:31

微信聊天记录备份指南:使用WeChatExporter轻松保存您的珍贵回忆

微信聊天记录备份指南:使用WeChatExporter轻松保存您的珍贵回忆 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 在数字时代,微信聊天记录承载着我…

阅读更多
Cortex-M指令集深度解析:饱和运算、位域操作与分支控制实战
2026/6/23 0:59:31

Cortex-M指令集深度解析:饱和运算、位域操作与分支控制实战

1. 从指令到效率:为什么Cortex-M指令集值得深挖如果你在嵌入式领域摸爬滚打了一段时间,尤其是跟ARM Cortex-M系列单片机打交道,那你肯定对“写寄存器”、“调库函数”这套流程熟得不能再熟了。但不知道你有没有过这样的感觉:项目代…

阅读更多
GIT修改用户名
2026/6/23 8:19:27

GIT修改用户名

在GIT中修改用户名可按以下步骤操作: 查看当前git的用户名,使用命令git config --list或git config user.name。修改git用户名,使用命令git config --global user.name "xxx(新的用户名)",将其中…

阅读更多
Win11Debloat:让你的Windows系统重获新生的终极优化工具
2026/6/22 10:07:50

Win11Debloat:让你的Windows系统重获新生的终极优化工具

Win11Debloat:让你的Windows系统重获新生的终极优化工具 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter and …

阅读更多
技术深度解析:m4s-converter实现原理与B站缓存视频转换最佳实践
2026/6/23 6:37:14

技术深度解析:m4s-converter实现原理与B站缓存视频转换最佳实践

技术深度解析:m4s-converter实现原理与B站缓存视频转换最佳实践 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter m4s-converter是一个…

阅读更多