Linux网络虚拟化技术之tun/tap
我们都知道,Linux实际是通过网络设备去操作和使用网卡的,系统安装了一个网卡之后会为其生成一个网络设备实例,比如eth0(或者叫enp7s0,不同发行版默认网卡命名规则不同)。随着网络虚拟化技术的发展,Linux支持创建出虚拟化的设备,可以通过虚拟化设备的组合实现多种多样的功能和网络拓扑。
常见的虚拟化设备有tun/tap、Veth、Bridge、802.1q VLAN device。
本文环境:
- OS:Ubuntu 18.04.3 LTS
先回顾一下经典的OSI七层网络模型:
┌───────┐
│ 应用层 │←第七层
├───────┤
│ 表示层 │
├───────┤
│ 会话层 │
├───────┤
│ 传输层 │
├───────┤
│ 网络层 │
├───────┤
│数据链路层│
├───────┤
│ 物理层 │←第一层
└───────┘
OSI七层参考模型
虚拟设备和物理设备的区别
对于一个网络设备来说,就像一个管道(pipe)一样,有两端,从其中任意一端收到的数据将从另一端发送出去。
比如一个物理网卡eth0,它的两端分别是内核协议栈(通过内核网络设备管理模块间接的通信)和外面的物理网络,从物理网络收到的数据,会转发给内核协议栈,而应用程序从协议栈发过来的数据将会通过物理网络发送出去。
那么对于一个虚拟网络设备呢?首先它也归内核的网络设备管理子系统管理,对于Linux内核网络设备管理模块来说,虚拟设备和物理设备没有区别,都是网络设备,都能配置IP,从网络设备来的数据,都会转发给协议栈,协议栈过来的数据,也会交由网络设备发送出去,至于是怎么发送出去的,发到哪里去,那是设备驱动的事情,跟Linux内核就没关系了,所以说虚拟网络设备的一端也是协议栈,而另一端是什么取决于虚拟网络设备的驱动实现。
tun/tap
tun分析实验
先上图说话:
上图中是tun设备的数据走向。
图中nsfocus_tun0就是tun0,是一个tun/tap虚拟设备,而eno16777736就是eth0。
socket、协议栈(Newwork Protocol Stack)和网络设备(eth0和tun0)部分都在内核层,其实socket是协议栈的一部分,这里分开来的目的是为了看的更直观。
从上图中可以看出它和物理设备eth0的差别,它们的一端虽然都连着协议栈,但另一端不一样,eth0的另一端是物理网络,这个物理网络可能就是一个交换机,而tun0的另一端是一个用户层的程序,协议栈发给tun0的数据包能被这个应用程序读取到,并且应用程序能直接向tun0写数据。
数据流向分析:
- User Application A通过套接字(socket A)发数据发给使用与eno16777736处于同一个网段ip的应用程序,数据走向为通过socket A发给协议栈,最后通过netdevice子系统中的eno16777736的设备驱动(以太网驱动)发送出去,这个是通过真实的物理网卡发送出去。
- User Application B通过套接字(socket B)发送数据给使用与nsfocus_tun0处于同一个网段ip的应用程序,数据走向为通过socket B发送给协议栈,最后通过netdevice子系统中的nsfocus_tun0的设备驱动(tun驱动)发送出去。由于tun设备没有对应真实的物理网卡,所以nsfocus_tun0对端收取数据的是User Application C。User Application C通过读写/dev/tun设备文件进行数据的收发。
其实一般User Application C就是个VPN程序(例如openvpn),它收到数据包之后,做一些跟业务相关的处理,然后构造一个新的数据包,将原来的数据包嵌入在新的数据包中,最后通过socket B将数据包转发出去,这时候新数据包的源地址变成了eth0的地址,而目的IP地址变成了一个其它的地址,比如是10.33.0.1(VPN服务器地址),协议栈根据本地路由,发现这个数据包应该要通过eth0发送出去,于是将数据包交给eth0,最后eth0通过物理网络将数据包发送出去。
从上面的流程中可以看出,数据包选择走哪个网络设备完全由路由表控制,所以如果我们想让某些网络流量走应用程序B的转发流程,就需要配置路由表让这部分数据走tun0。
示例程序
为了使用tun/tap设备,用户层程序需要通过系统调用打开/dev/net/tun获得一个读写该设备的文件描述符(FD),并且调用ioctl()向内核注册一个TUN或TAP类型的虚拟网卡(实例化一个tun/tap设备),其名称可能是tap7b7ee9a9-c1/vnetXX/tunXX/tap0等。
这里写了一个程序,它收到tun设备的数据包之后,只打印出收到了多少字节的数据包,其它的什么都不做。
|
|
编译、运行程序,会发现多出一个网络设备
|
|
tun0
就是新增的网络设备,现在给它配置一个ip,查看接口信息
|
|
这时候我们ping地址192.168.10.12
|
|
发现tun
程序收到了数据
tun和tap区别
两者很类似,只是tun和tap设备他们工作的协议栈层次不同,tap等同于一个以太网设备,用户层程序向tap设备读写的是二层数据包如以太网数据帧,tap设备最常用的就是作为虚拟机网卡。tun则模拟了网络层设备,操作第三层数据包比如IP数据包,openvpn使用TUN设备在C/S间建立VPN隧道。
tap分析实验
tap设备最常见的用途就是作为虚拟机网卡。