Linux虚拟网络设备 - tap/tun
tap/tun常用于隧道通讯,通过一个字符设备来实现用户态和内核态的通讯,字符设备一端连接着用户空间,一端连接着内核空间。
对应的字符设备文件位置:
- tap: /dev/tap0
- tun: /dev/net/tun
当应用程序打开字符设备文件时,驱动程序会创建并注册相应的虚拟设备接口,以tunX或tapX命名。应用程序关闭设备文件时,驱动程序会删除tunX和tapX网络虚拟设备,并删除建立起来的路由信息。
两个设备的不同点:
- tap是一个二层网络设备,只能处理二层的以太网帧
- tun是一个点对点的三层网络设备,只能处理处理三层的IP数据包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| ┌──────────────┐ │ │ │ APP │ │ │ └───────┬──────┘ │ │ │ │ │ │ ┌────────────▼──────────┐ │ │ ─ ─ ─ ─ ─ ─│ /dev/net/tun ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ │ └────────────┬──────────┘ │ │ │ │ │ ┌───────▼──────┐ ┌──────────────┐ │ │ │ │ │ tunX ├────────────────▶│Network Stack │ │ │ │ │ └──────────────┘ └──────────────┘
|
tun设备应用举例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ APP A │ │ APP B │◀┐ │ │ │ │ │ └───────┬──────┘ └───────┬──────┘ │ │ │ │ │ │ │ 1│ │ │ │ 5│ │ │ │ │ ─ ─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ │ │ │ │ │ 4│ │ │ │ ┌────────────▼────────────────────────▼─────┐ │ │ │ │ │ Network Stack │ │ │ │ │ └────────────┬───────────────────────┬──────┘ │ │ │ │ 6│ 3│ │ │ │ │ ┌───────▼──────┐ ┌─▼─────────┴──┐ │ │ │ │ 10.1.1.11 │ eth0 │ │ tun0 │ 192.168.1.11 │ │ │ │ └───────┬──────┘ └──────────────┘ │ 7│ │ ▼
10.1.1.100 / 192.168.1.100
|
应用程序A要发送数据到其他物理机192.168.1.100,由于物理网络环境下只有10.1.1.11和10.1.1.100是相互连通的,192.168.1.11和192.168.1.100是不通的,为了192.168.1.11和192.168.1.100能够进行通讯,需要将数据包进行一次封装。
应用程序B是通过打开字符设备文件/dev/net/tun0的方式来打开网络设备
流程如下:
- A构造数据包,目的ip为192.168.1.100,并发送给协议栈
- 协议栈根据数据包中的ip地址,匹配路由规则,要从tun0出去
- 内核协议栈将数据包发送给tun0网络设备
- tun0发送应用程序B打开,于是将数据发送给应用程序B
- B收到数据包后,在用户态构造一个新的数据包,源IP为eth0的IP 10.1.1.11,目的IP为配置的对端10.1.1.100,并封装原来的数据包
- 协议栈根据当前数据包的IP地址选择路由,将数据包发送给eth0
reference