tun/tap虚拟网卡收发机制解析

本章要研究的是openxxx的收发原理,实际上研究就是研究tun/tap网卡驱动的相关原理。

收发机制原理

共性

openxxx开启后,出现了 tap0 虚拟网卡,如下图:

在这里插入图片描述
tap类型的虚拟网卡是tun/tap驱动程序实现的,也就是说 openxxx 基于 tun/tap 虚拟网卡驱动了隧道包封装。

其中,tap表示虚拟的是以太网设备,tun表示虚拟的是点对点设备,这两种设备针对网络包实施不同的封装。

那么,虚拟网卡和物理网卡的转发原理是什么(数据包肯定要从物理网卡才能流出)?通信包又是如何封装的?这两点是本小节的主要关注点。

虚拟网卡和物理网卡的通信

在这里插入图片描述
从这个路由表可以看出,网段是10.8.0的IP数据包都会被发到tap0网卡。tap0网卡属于网卡,同样被系统内核的网络设备管理系统来管理。

站在管理系统的视角来看,虚拟网卡和实际网卡一样,都是网络设备。网络设备收到的数据,都会发到上层协议栈处理,而协议栈发出的数据,同样也会发动对应的网络设备。下图简要表示了这个结构:
在这里插入图片描述
协议栈根据目的IP来决定将数据包路由到哪一个网卡,那么虚拟网卡下层的“物理设备”是什么?

因为数据包肯定是从物理网卡出去的,所以虚拟网卡发出去的数据包最终要发到物理网卡。而基于tun/tap的虚拟网卡,其实现是通过用户态程序来将数据包转交。

而内核态和用户态的数据交互,在Linux下面有多种方式,比如通过Socket或者文件系统管理的文件交互或者设备文件。Linux下面的设备文件分为三大类:块设备、网络设备、字符设备。
块设备主要是存储类型的设备;网络设备使用socket访问;而字符设备就是以字节流形式通讯的I/O设备。

这里tun/tap驱动程序选择的是以字符设备(字符设备文件,Linux一切皆文件)作为传输通道。细节图如下(只看红线部分):
在这里插入图片描述
图中虚拟网卡将数据发送到字符设备文件,然后用户程序读取到文件内容后,进行处理,处理完以后将其发往协议栈,最后经由物理网卡发送出去。

可以看出,虚拟网卡既负责实现物理网卡的功能,又负责实现和字符设备的交互。所以tun/tap驱动程序实际上分成了两块:网卡驱动和字符设备驱动。

网络传输包格式

openxxx搭建好以后,我们都是直接使用局域网IP通信的,局域网IP数据包不能直接在公网上路由,我们其他应用发出的原始数据包示意图如下(我们只关注IP层):
在这里插入图片描述

这样的数据经过协议栈后自然会转发到虚拟网卡tap0,再有虚拟网卡tap0将其发送到openxxx,然后openxxx内部将这个完整的数据包进行加密,再封装上公网IP包头,数据包示意图如下:
在这里插入图片描述
所以实际上在网络中传输,路由依靠的仍然是公网IP头进行数据包的路由。

至于openxxx怎么知道内网和公网IP的映射,这点在openxxx客户端建立连接的时候就已经确认了。因为建立连接的时候openxxx会指定客户端的内网IP,并且由于能够收到客户端的握手信息,所以能够从包中提取到客户端实际的公网IP。

接收机制

在这里插入图片描述
接收机制如上图所示,蓝线是公网IP,红线是解密后的内网IP包。经过两次协议栈的路由,最终将数据发到用户程序。结合数据包的流转即可得知过程。

发送机制

在这里插入图片描述
发送机制如上图所示,红线是内网IP,蓝线是加密过后的公网IP包。包格式如上文所述。根据数据包的流转,即可得知过程。

服务器端的转发机制

在这里插入图片描述
服务端转发的时候并不需要经过tap虚拟网卡,因为数据包首先会到openxxx(参见接收机制),openxxx内部会得知该数据包是要转发到另外一台“局域网客户端的”,所以根据建立连接时的公网IP-内网IP映射关系,将公网IP包的目的IP改变即可。
所以蓝线部分直接就将数据包发送出去了。

为了验证猜想,直接将服务器端的tap0虚拟网卡关闭,一段时间后客户端之间仍然可以正常通信,所以在转发机制这边并不需要走虚拟网卡。

发布了39 篇原创文章 · 获赞 74 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/zhou307/article/details/102806500