linux Tun/Tap 虚拟网卡

一、TUN、TAP 虚拟网卡的工作原理:

+----------------------------------------------------------------+
|                                                                |
|  +--------------------+      +--------------------+            |
|  | User Application A |      | User Application B |<-----+     |
|  +--------------------+      +--------------------+      |     |
|               | 1                    | 5                 |     |
|...............|......................|...................|.....|
|               ↓                      ↓                   |     |
|         +----------+           +----------+              |     |
|         | socket A |           | socket B |              |     |
|         +----------+           +----------+              |     |
|                 | 2               | 6                    |     |
|.................|.................|......................|.....|
|                 ↓                 ↓                      |     |
|             +------------------------+                 4 |     |
|             | Newwork Protocol Stack |                   |     |
|             +------------------------+                   |     |
|                | 7                 | 3                   |     |
|................|...................|.....................|.....|
|                ↓                   ↓                     |     |
|        +----------------+    +----------------+          |     |
|        |      eth0      |    |      tun0      |          |     |
|        +----------------+    +----------------+          |     |
|    10.32.0.11  |                   |   192.168.3.11      |     |
|                | 8                 +---------------------+     |
|                |                                               |
+----------------|-----------------------------------------------+
                 ↓
         Physical Network

应用B是代理程序。应用A为用户端程序(如浏览器),应用A的发出的数据包由tun0接收(通过路由表拦截),tun0将其转发给应用B,应用B处理后再发给以太网卡eth0,eth0发送给物理网络。

根据应用B的处理方式不同,可以有不同的应用。

二、应用

实现点对点隧道(类似openvpn):需要两台服务器分别实现TUN 设备的接入

这里外层IP数据包用于两台TUN设备通信,内层数据包包含中原始的访问请求。从而实现端到端的数据的传输。

实现全局代理(类似leaf):

前提:应用程序可以通过 read(fd, buf, len) 从 /dev/net/tun 获得完整 IP 数据报,再通过 write(tun_fd, buf, n) 修改 IP 数据报。至此,应用程序便有了控制 IP 层数据报的能力。

问题:如何直接拦截与解析应用层的数据包?

方案一:直接从TUN 读到的原始IP数据报中提取TCP/UDP头与应用层负载(此外,可以直接从IP数据包中读取目标IP地址,如果应用层解析不到的话)。这部分可以借用一些工具库去处理,比如 libcap等。

方案二:应用从 TUN 读取原始 IP 报文,若是发往某服务的请求,就修改报文的目标 IP/端口为本地监听地址,然后 write 回 TUN。内核收到写回 TUN 的数据后,会按照原生流程拆 IP/TCP 头并将纯净的应用层负载送入对应的 socket 缓冲区。此时,应用只需基于普通的 socket(AF_INET, SOCK_STREAM) 或 recv() 接口读取即可拿到应用层数据。如 leaf,先在用户态解析 DNS 和 IP,返回一个假 IP(通常在私有网段),数据包就会经过内核程序再发送回来,再由leaf去处理应用层的数据。

总结:方案二,将网络层数据拆包的处理交给内核态的网络协议栈处理,对于只关心应用层数据包的程序来说更加方便与高效。

参考资料


https://www.zhaohuabing.com/post/2020-02-24-linux-taptun
https://segmentfault.com/a/1190000009249039

posted on 2025-04-26 10:09  Lemo_wd  阅读(151)  评论(0)    收藏  举报

导航