在 Linux 网络虚拟化的领域中,TUN/TAP 设备发挥着不可或缺的核心作用。它们是容器网络、VPN技术与虚拟机网络架构的基石。深入理解 TUN/TAP 设备,不仅是掌握 Linux 网络栈的关键,也是进一步探索云原生网络插件(例如 flannel)的必经之路。
概述:什么是TUN与TAP设备?
TUN 和 TAP 是 Linux 内核提供的两种虚拟网络设备,专门用于创建和管理虚拟网络接口。
TUN(Network Tunneling)
- TUN 设备模拟的是一个点对点的网络接口,通常用于实现路由功能。它工作在网络层(IP层,L3),处理 IP 数据包。
- TUN 设备是许多 VPN(虚拟专用网络) 解决方案的核心,能够将 IP 数据包封装在安全的隧道中进行传输。
TAP(Terminal Access Point)
- TAP 设备模拟的是以太网设备,工作在数据链路层(以太网层,L2),负责处理完整的以太网帧。
- TAP 设备通常用于虚拟机和容器之间的网络通信,可以让不同的虚拟网络设备共享同一物理网络接口。
TUN与TAP的核心区别
理解两者的区别至关重要:
tun 设备:虚拟化点对点网络接口,工作在网络层(L3),专门处理IP数据包。由于 tun 设备没有 MAC 地址,因此无法处理 ARP 请求或以太网广播。
tap 设备:虚拟化以太网接口,工作在数据链路层(L2),处理以太网帧。tap 设备拥有 MAC 地址,可以参与桥接网络,其行为就像一块虚拟的物理网卡。
核心工作原理:连接用户空间与内核空间
1. TUN/TAP 设备与物理网卡的本质区别
要理解其价值,首先要看它们与物理网卡的对比:
- 物理网卡:一端连接外部物理网络,另一端连接内核的网络协议栈。
- TUN/TAP设备:在操作系统内部,它们一端连接用户空间的应用程序,另一端连接内核的网络协议栈。它们的数据源并非物理链路,而是用户态程序。

2. TUN/TAP 设备的工作原理详解
从网络协议栈的视角看,TUN/TAP 设备与物理网卡并无二致。其不同之处在于,TUN/TAP 设备的数据来自用户态程序,这赋予了它们巨大的灵活性。
TUN/TAP 设备通过 Linux 的“一切皆文件”哲学,利用设备文件 /dev/net/tun 实现内核态与用户态之间的数据交互。访问这个设备文件会调用相应的设备驱动,驱动便成为连接内核与用户态的桥梁。

普通的物理网卡通过网线收发数据包,而 TUN/TAP 设备通过操作 /dev/net/tun 这个字符设备文件来收发数据包。应用程序的数据收发过程如下:
- 数据发送:应用进程通过打开
/dev/net/tun 字符设备,并使用 ioctl 系统调用创建一个虚拟网络接口(如 tun0 或 tap0)。ioctl 调用会返回一个文件描述符 fd。应用程序通过向这个 fd 写入格式化的数据(IP包或以太网帧),数据便会通过虚拟网卡驱动送入内核的 TCP/IP 协议栈。对于协议栈而言,这些数据就像是从一块真实网卡接收到的一样。
- 数据接收:当内核网络协议栈有数据需要发送给这个虚拟接口(
tun0 或 tap0)时,应用程序便可以通过之前获得的文件描述符 fd 读取到这些数据,并进行自定义处理(如加密、转发等)。
TAP 与 TUN 设备的工作原理完全相同,主要区别在于处理的数据单元:
- TUN 设备 的
/dev/net/tun 文件传输的是 IP 包,因此只能工作在网络层(L3)。它无法与物理网卡进行二层桥接,但可以通过三层路由(如 ip_forward)与物理网络连接。
- TAP 设备 的
/dev/net/tun 文件传输的是 以太网帧。因此,TAP 虚拟设备在功能上更接近真实的物理网卡,可以直接加入到 Linux 网桥 中,实现与物理网卡的二层桥接。
重要注意事项:
- TUN 和 TAP 设备都是通过打开同一个
/dev/net/tun 字符设备文件,并使用 ioctl 指定类型来创建的。创建的设备接口(如 tun0)不会出现在 /dev/ 目录下,而是可以在 /sys/class/net/ 目录下找到。
/dev/net/tun 是一个“克隆设备”,是创建所有 TUN/TAP 虚拟接口的起点。每次以读写模式打开它,内核都会为其分配一个独立的文件结构实例,代表一个不同的字符设备通道。
3. TUN/TAP 驱动的构成
TUN/TAP 驱动程序由两部分协同工作:
- 网卡驱动部分:负责从 TCP/IP 协议栈 接收网络数据包并“发送”出去,或者将“接收”到的数据包传递给协议栈处理。
- 字符设备驱动部分:负责通过
/dev/net/tun 在内核与用户态程序之间传输数据包,模拟了物理链路上的数据收发。用户态程序通过 ioctl、read 和 write 系统调用与之交互。
TUN/TAP设备的典型应用场景
1. 虚拟专用网络(VPN)
这是 TUN 设备的经典应用。VPN 客户端(如 OpenVPN)会创建一个 TUN 设备(tun0)。当操作系统需要访问远程网络(如公司内网)时,目标地址为内网 IP 的数据包会被路由到 tun0。随后,VPN 程序从 tun0 对应的文件描述符中读取原始 IP 包,进行加密和封装(例如封装成 UDP 包),再通过真实的物理网卡发送给 VPN 服务器。服务器解密后,将原始 IP 包注入其网络栈,最终送达目标。这为用户创建了一条安全的“隧道”。想深入了解其实现,可以探索 云栈社区 中关于网络协议和 VPN 的更多讨论。
2. 虚拟机与容器网络
在虚拟化及容器化环境中,TAP 设备扮演了关键角色。当 QEMU 等虚拟机管理器启动一台虚拟机时,通常会在宿主机上创建一个 TAP 设备(如 tap0),作为虚拟机的“虚拟网卡”。这个 tap0 设备会被添加到宿主机的 Linux 网桥(如 br0)中,物理网卡也可能加入此网桥。这样,虚拟机发出的以太网帧通过 TAP 设备被宿主机上的程序读取并转发到网桥,从而实现与外部网络或其他虚拟机的通信。这种机制正是许多 容器网络 方案(如 Docker 的 bridge 模式)和云原生基础设施网络模型的基础。这类场景通常涉及复杂的配置管理和编排,相关的知识可以在 云栈社区 的云原生板块找到更系统的资料。
总结
TUN/TAP 设备巧妙地利用了 Linux 内核的特性,通过字符设备文件 /dev/net/tun 在内核网络协议栈与用户空间程序之间架起了一座高效的桥梁。尽管它们完全由软件实现,但在内核看来,其行为与物理网卡无异。
其核心价值在于将网络数据包的处理能力开放给了用户空间。这种设计带来了极大的灵活性,催生了 VPN、虚拟化网络、软件定义网络(SDN)以及复杂的云原生基础设施等众多强大应用。理解它们,是深入 Linux 网络世界和现代 运维/DevOps 实践的重要一步。
|