一.虚拟网卡介绍
虚拟网卡通常称为为tap/tun。
tap/tun 是 Linux 内核 2.4.x 版本之后实现的虚拟网络设备,不同于物理网卡靠硬件网卡实现,tap/tun 虚拟网卡完全由软件来实现,功能和硬件实现完全没有差别,它们都属于网络设备,都可以配置 IP,都归 Linux 网络设备管理模块统一管理。
二.物理网卡收发包流程
1.收包:外界向该物理网卡发送数据包时,外界发送到网卡的数据包最终会传输到内核空间的网络协议栈中
2.发包:本机要从物理网卡发送数据包时,数据将从内核的网络协议栈传输到网卡,网卡负责将数据发送出去
注:现在的网卡具备DMA能力,所以网卡和网络协议栈之间的数据传输由网卡负责,而非由内核亲自占用CPU来执行读和写
一般来说,数据的起点和终点是用户程序,所以多数时候的数据需要在用户空间和内核空间(网络协议栈)再传输一次:
物理网卡需要通过网卡驱动在内核中注册后才能工作,它在内核网络协议栈和外界网络之间传递数据,用户可以为物理网卡配置网卡接口属性,比如IP地址,这些属性都配置在内核的网络协议栈中。
三.虚拟网卡收发包流程
内核也可以直接创建虚拟的网卡,只要为虚拟网卡提供网卡驱动程序,使其在内核中可以注册成为网卡设备,它就可以工作。
从Linux内核3.x版本开始,物理网卡和虚拟网卡是平等的设备,它们都会在注册时创建net_device数据结构来保存(物理或虚拟)设备信息。
相比于物理网卡负责内核网络协议栈和外界网络之间的数据传输,虚拟网卡的两端则是内核网络协议栈和用户空间,它负责在内核网络协议栈和用户空间的程序之间传递数据。
1.收数据包:
数据如何从内核空间到用户空间呢?这里用到一个字符设备。
在 Linux 中,用户空间和内核空间的数据传输有多种方式,字符设备就是其中的一种。tap/tun 通过驱动程序和一个与之关联的字符设备,来实现用户空间和内核空间的通信接口。
在 Linux 内核 2.6.x 之后的版本中,tap/tun 对应的字符设备文件分别为:
tap:/dev/tap0
tun:/dev/net/tun
设备文件即充当了用户空间和内核空间通信的接口。当应用程序打开设备文件时,驱动程序就会创建并注册相应的虚拟设备接口,一般以 tunX 或 tapX 命名。当应用程序关闭文件时,驱动也会自动删除 tunX 和 tapX 设备,还会删除已经建立起来的路由等信息。
tap/tun 设备文件就像一个管道,一端连接着用户空间,一端连接着内核空间。当用户程序向文件 /dev/net/tun 或 /dev/tap0 写数据时,内核就可以从对应的 tunX 或 tapX 接口读到数据,反之,内核可以通过相反的方式向用户程序发送数据。
2.发包流程
Tap/Tun如何和网络协议栈传输数据
tap/tun 通过实现相应的网卡驱动程序来和网络协议栈通信。一般的流程和物理网卡和协议栈的交互流程是一样的,不同的是物理网卡一端是连接物理网络,而 tap/tun 虚拟网卡一般连接到用户空间。
如上图所示,假设APP A要访问 192.168.1.200的服务器,数据包经过协议栈如下几个步骤:
1.APP A发送数据包到内核协议栈
2.经过内核协议栈的路由判决,判断下一个出接口为TunX
3.TunX接收到数据后,将数据包发送到字符设备/dev/net/tun
4.APP B从字符设备读取出数据包,已知要访问192.168.1.200的服务器是要发10.10.1.200目的地址
5.APP B将读取出的数据包作为原始数据,发送到内核协议栈
6.内核协议栈接收到APP B的数据(原数据包),进行数据封装,包一层新IP头,源IP为10.10.1.200,目的IP为10.10.1.200
7.数据包从Eth0物理接口出去
8.数据包发到对端服务器,进行上述1~7的逆过程