【NetDevOps】新一代网工需要了解的那点事儿(四)---tun/tap

4 tun/tap

  虚拟网络设备也归内核的网络设备管理子系统管理。对于Linux内核网络设备管理模块来说,虚拟设备和物理设备没有区别,都是网络设备,都能配置IP,从网络设备来的数据,都会转发给协议栈,协议栈过来的数据,也会交由这些网络设备发送出去,至于是如何发送、发送到哪,这都由设备驱动来完成,跟Linux内核就没关系了。

4.1 tun/tap概述

  从Linux文件系统来看,它们是用户可以用文件来操作的字符设备;但是从网络虚拟化的角度来看,它们是虚拟网卡,一端是APP一端是网络协议栈。与普通的网络接受发数据不同,tun/tap设备比较特殊,它是通过文件来收发数据包。如下图所示,tunX 和上面的 eth0 在逻辑上面是等价的, tunX 也代表了一个网络接口,虽然这个接口是系统通过软件所模拟出来的。网卡接口 tunX 所代表的虚拟网卡通过文件 /dev/tunX 与我们的应用程序(App) 相连,应用程序每次使用 write 之类的系统调用将数据写入该文件,这些数据会以网络层数据包的形式,通过该虚拟网卡,经由网络接口 tunX 传递给网络协议栈,同时该应用程序也可以通过 read 之类的系统调用,经由文件 /dev/tunX 读取到协议栈向 tunX 传递的所有数据包。其实这里的tunX和其他普通网卡基本一样,唯独的区别是这个虚拟网卡没有MAC地址,由于tunX仅能虚拟到网络层,所以要MAC地址也没用。但如果是tapX网卡则不同,因为它比runX更深入一层。对于协议栈来看tapX和物理网卡是没有区别的。

 +-------------------------------------------------------------------------------+
 |                                                                               |
 |            +--------------+                             +---------------+     |
 |            |     APP      |                             |  Socket API   |     |
 |            |              |                             |               |     |
 |            +------+-------+                             +------+--------+     |
 |                   |                                            |              |
 |                   |                                            |              |
 | USER       +------+--------+                                   |              |
 +------------+  /dev/tunX    +--------------------------------------------------+
 |LINUX KERNEL|               |                                   |              |
 |            +-------+-------+                    +--------------+-----------+  |
 |                    |                            |                          |  |
 |                    |                            |  Network Protocal Stack  |  |
 |                    |                            |                          |  |
 |                    |                            +--------------+-----------+  |
 |                    |                                           |              |
 |                    |                                           |              |
 |                    |                                           |              |
 |                    |                                           |              |
 |                    |         +--------------+                  |              |
 |                    |         |              |                  |              |
 |                    +---------+     tunX     +------------------+              |
 |                              |              |                                 |
 |                              +--------------+                  By:[F0rGeEk]   |
 |                                                                               |
++-------------------------------------------------------------------------------+

4.2 典型使用场景

  较为常见的tun/tap使用场景有数据加密、数据压缩等,这里我们主要讲解最常用的VPN。它是利用tun设备做UDP的VPN,如下图所示。在用户层有两个APP1和APP2,Linux内核层有socket、网络协议站、网络设备。其中socket实质上是网络协议栈的一部分。这里我们将eth0的IP设定为10.8.8.11,eth0网络的网关为10.8.8.254;tun0的IP设定为12.1.1.11。我们这里假设VPN用户是eth0网络10.8.8.0/24中的某一台主机,这台主机本地有12.1.1.0/24网络,我们的目的是通过APP 1能与VPN主机本地网络中的成员进行通讯。

+--------------------------------------------------------------------------+
|   +---------------------+           +-----------------------+            |
|   |                     |           |                       |            |
|   |        AAP 1        |           |         APP 2         <-------+    |
|   |                     |           |                       |       |    |
|   +---------+-----------+           +-----------+-----------+       |    |
|             |                                   |                   |    |
|             |                                   |                   |    |
+--------------------------------------------------------------------------+
|             |                                   |                   |    |
|             |                                   |                   |    |
|             v                                   v                   |    |
|      +------+------+                     +------+------+            |    |
|      |             |                     |             |            |    |
|      |   Socket 1  |                     |  Socket 2   |            |    |
|      |             |                     |             |            |    |
|   +--+-------------+---------------------+-------------+-----+      |    |
|   |                                                          |      |    |
|   |                  Network Protocal Stack                  |      |    |
|   |                                                          |      |    |
|   +---------+-----------------------------------+------------+      |    |
|             |                                   |                   |    |
|             |                                   |                   |    |
|             |                                   |                   |    |
|     +-------v------+                     +------v-------+           |    |
|     |              |                     |              |           |    |
|     |     eth0     |                     |     tun0     |           |    |
|     |              |                     |              |           |    |
|     +-------+------+                     +------+-------+           |    |
|             | 10.8.8.11/24                      | 12.1.1.11/24      |    |
|             |                                   +-------------------+    |
|             |                                                            |
|             |                                             By:[F0rGeEk]   |
+--------------------------------------------------------------------------+
              v
       Physical Network

这里假设10.8.8.33要与12.1.1.33通过VPN互访,下面我们来看看数据包的流程:

  1. 首选APP 1通过socket 1发送了一个目的地为12.1.1.33的数据包,socket将该数据包转发给网络协议栈;
  2. 协议栈收到该数据包后,根据本地路由规则进行匹配,将该数据包扔给tun0处理;
  3. tun0收到数据包后,由于另一端连着APP 2,所以它会直接将数据包转发至APP 2;
  4. APP 2收到数据包后,根据需要进行重构,重构时会将原有的数据包原封不动的包在新数据包中,然后再有APP 2发送出去。新数据包的源地址会变成eth0的地址10.8.8.11,而目的地址将会变成10.8.8.33;
  5. Socket收到由APP 2发出的数据包后,会直接转发给协议栈;
  6. 协议栈收到数据包后,匹配本地路由规则,将数据包转发给eth0;
  7. eth0收到数据包后,会直接通过物理网络将数据包发送出去;
  8. 当10.8.8.33收到数据包后,首先是打开数据包读取里面的原始数据,并将该数据包转发给12.1.1.33;如果12.1.1.33收到数据包并且回复的话,那么当收到12.1.1.33回复的数据包后进行数据包的重构,同样将原始数据封装在新的数据包中,再由原路返回;
  9. 这样最终APP 1即通过VPN完成了与12.1.1.33的通信。

4.3 tun与tap的区别

  通过1.6.2小节的通信流程来看,tun/tap设备的用处是将协议栈中的部分数据包转发给用户空间的应用程序,再由用户空间的程序来处理这个数据包。tun/tap设备不仅能做基于DUP的VPN,类似的tunnel以及IPSec都是比较常用的场景。虽然它们的工作方式完全相同,但还是有一些区别:

  • 户层程序通过tun设备只能读写IP数据包,而通过tap设备能读写链路层数据包;
  • tun设备相当于是一个三层设备,,它无法与物理网卡做 bridge,但是可以通过三层交换(如 ip_forward)与物理网卡连通。可以使用ifconfig之类的命令给该设备设定 IP 地址;
  • tap设备则相当于是一个二层设备,可以工作在数据链路层,拥有 MAC 层功能,可以与物理网卡做 bridge,支持 MAC 层广播。可以通过ifconfig之类的命令给该设备设定 IP 地址,甚至还可以给它设定 MAC 地址。
posted @ 2020-04-01 10:58  为极客而生  阅读(415)  评论(0编辑  收藏  举报