TUN/TAP概述

在云计算时代,虚拟机和容器已经成为标配。它们背后的网络管理都离不开一样东西,就是虚拟网络设备,或者叫虚拟网卡,tap/tun 就是在云计算时代非常重要的虚拟网络网卡。

TUN/TAP 是什么

tap/tun 是 Linux 内核 2.4.x 版本之后实现的虚拟网络设备,不同于物理网卡靠硬件网卡实现,tap/tun 虚拟网卡完全由软件来实现,功能和硬件实现完全没有差别,它们都属于网络设备,都可以配置 IP,都归 Linux 网络设备管理模块统一管理。

tun是虚拟网卡,网桥相当于虚拟交换机,根据mac转发数据报文到不同的网卡

TUN工作机制

TUN 设备是一种虚拟网络设备,通过此设备,程序可以方便得模拟网络行为。

物理网卡设备的工作流程

tun-1

所有物理网卡收到的包会交给内核的 Network Stack 处理,然后通过 Socket API 通知给用户程序。

TUN 的工作方式

tun-2

普通的网卡通过网线收发数据包,但是 TUN 设备通过一个文件收发数据包。所有对这个文件的写操作会通过 TUN 设备转换成一个数据包送给内核;当内核发送一个包给 TUN 设备时,通过读这个文件可以拿到包的内容。

基于TUN设备的udp vpn

如果我们使用 TUN 设备搭建一个基于 UDP VPN,那么整个处理过程就是这样:

tun-3

数据包会通过内核网络栈两次。但是经过 App 的处理后,数据包可能已经加密,并且原有的 ip 头被封装在 udp 内部,所以第二次通过网络栈内核看到的是截然不同的网络包。

TUN数据传输过程

作为网络设备,tap/tun 也需要配套相应的驱动程序才能工作。tap/tun 驱动程序包括两个部分,一个是字符设备驱动,一个是网卡驱动。这两部分驱动程序分工不太一样,字符驱动负责数据包在内核空间和用户空间的传送,网卡驱动负责数据包在 TCP/IP 网络协议栈上的传输和处理。

用户空间与内核空间的数据传输

在 Linux 中,用户空间和内核空间的数据传输有多种方式,字符设备就是其中的一种。tap/tun 通过驱动程序和一个与之关联的字符设备,来实现用户空间和内核空间的通信接口。

在 Linux 内核 2.6.x 之后的版本中,tap/tun 对应的字符设备文件分别为:

tap:/dev/tap0
tun:/dev/net/tun

2.6内核之前TUN对应的文件是/dev/tun,在2.6以后,TUN设备就会对应于文件是/dev/net/tun。

设备文件即充当了用户空间和内核空间通信的接口。当应用程序打开设备文件时,驱动程序就会创建并注册相应的虚拟设备接口,一般以 tunX 或 tapX 命名。当应用程序关闭文件时,驱动也会自动删除 tunX 和 tapX 设备,还会删除已经建立起来的路由等信息。

tap/tun 设备文件就像一个管道,一端连接着用户空间,一端连接着内核空间。当用户程序向文件 /dev/net/tun 或 /dev/tap0 写数据时,内核就可以从对应的 tunX 或 tapX 接口读到数据,反之,内核可以通过相反的方式向用户程序发送数据。

431521-20190228112857683-661682487

tap/tun 和网络协议栈的数据传输

tap/tun 通过实现相应的网卡驱动程序来和网络协议栈通信。一般的流程和物理网卡和协议栈的交互流程是一样的,不同的是物理网卡一端是连接物理网络,而 tap/tun 虚拟网卡一般连接到用户空间。

如下图的示意图,我们有两个应用程序 A、B,物理网卡 eth0 和虚拟网卡 tun0 分别配置 IP:10.1.1.11 和 192.168.1.11,程序 A 希望构造数据包发往 192.168.1.0/24 网段的主机 192.168.1.1。

431521-20190228112909811-1280596515--1-

网络协议栈指 linux内核的网络封装流程 如传输层,网络层,链路层的处理

基于上图,我们看看数据包的流程:

  • 应用程序 A 构造数据包,目的 IP 是 192.168.1.1,通过 socket A 将这个数据包发给协议栈。
  • 协议栈根据数据包的目的 IP 地址,匹配路由规则,发现要从 tun0 出去。
  • tun0 发现自己的另一端被应用程序 B 打开了,于是将数据发给程序 B.
  • 程序 B 收到数据后,做一些跟业务相关的操作,然后构造一个新的数据包,源 IP 是 eth0 的 IP,目的 IP 是 10.1.1.0/24 的网关 10.1.1.1,封装原来的数据的数据包,重新发给协议栈。
  • 协议栈再根据本地路由,将这个数据包从 eth0 发出。

后续步骤,当 10.1.1.1 收到数据包后,会进行解封装,读取里面的原始数据包,继而转发给本地的主机 192.168.1.1。当接收回包时,也遵循同样的流程。

在这个流程中,应用程序 B 的作用其实是利用 tun0 对数据包做了一层隧道封装。其实 tun 设备的最大用途就是用于隧道通信的。

tun的接收流程

20191029121042583

  • 当linux物理网卡收到网络包后,根据网络协议栈匹配到对应端口的服务openvpn
  • openvpn解密出内网包,将内网包内容写入tun字符设备,从而进入虚拟网卡
  • 虚拟网卡的另一端为协议栈
  • 协议栈根据ip及端口匹配到用户程序

tun发送流程

2019102912105969

  • 用户程序发送的数据包到达协议栈
  • 协议栈匹配到网卡虚拟网卡
  • 虚拟网卡将数据写入字符设备文件
  • openvpn读取字符设备文件内容
  • 将数据包封装为新的数据包,源ip&mac为网卡1的ip&mac,将新的数据包发送到公网

上述流程是发送至另一机器的虚机上;当用户程序发送到另一机器时,由于ip包直接匹配到网卡1,所以不会走上述封装的过程。openvpn是一个软件需要自己安装。

TAP/TUN设备区别

TAP 设备与 TUN 设备工作方式完全相同,区别在于:

  • tap 和 tun 虽然都是虚拟网络设备,但它们的工作层次还不太一样
  • TUN是一个点对点的三层设备(或网络层设备)
  • TUN 设备的 /dev/tunX 文件收发的是 IP 层数据包,只能工作在 IP 层,无法与物理网卡做 bridge,但是可以通过三层交换(如 ip_forward)与物理网卡连通。
  • TAP设备是一个二层设备(或者以太网设备)
  • TAP 设备的 /dev/tapX 文件收发的是 MAC 层数据包,拥有 MAC 层功能,可以与物理网卡做 bridge,支持 MAC 层广播

TUN/TAP操作

确认内核是否支持tun/tap

确认内核是否有tun模块,并加载内核模块

anbh24puql

执行以上命令后,出现如上输出,说明模块加载成功

创建和配置虚拟网卡

  • 确认是否有tunctl命令

如果没有通过yum安装即可,centos6通过直接通过yum install tunctl -y安装;centos7安装之前需要新增yum源vim /etc/yum.repos.d/nux-misc.repo

uaa8x0rc9x

  • 加载yum源并装包
yum repolist 
yum --enablerepo=nux-misc install tunctl
  • 创建虚拟网卡设备

86ou1b5v0l
经过如上操作后,虚拟网卡已经建立和配置好了。

  • 再用另一个命令添加一个tap1
    p64nm3ypuy

  • 删除tap0、tap1

tg7w0lf432