Linux 虚拟网络设备 tun/tap veth pair

本篇主要介绍一下 linux 下面的 虚拟网络设备 tun/tap veth pair

image-20220514084502384

随着容器逐步取代虚拟机,成为云基础架构的标准,然而容器的网络管理部分是离不开 Linux虚拟网络设备的,所以了解常用的Linux 虚拟网络设备对于我们云理解网络架构很有帮助

Linux虚拟网络的背后都是由一个个虚拟设备构成的,在虚拟化技术还没出现之前,计算机网络系统一般都只包含物理网卡设备

image-20220514072600084

由于虚拟化技术的出现,网络也需要被虚拟化,虚拟网络变得很复杂,将一台主机里面实现 如 交换机,路由,隔离,等等网络功能,从而为容器时代提供基础

1.什么是虚拟网络设备

在Linux中 网络设备的驱动程序不直接和内核协议栈交互,而是通过内核的网络设备管理模块作为中间桥梁,这样做的好处是,驱动程序不需要了解网络协议栈的细节,协议栈也不需要针对特定驱动处理数据包。

对于内核网络设备管理模块来说,虚拟设备和物理设备 是没有区别的 都是网络设备 都能配置IP

总的来说,虚拟网络设备与物理网络设备没有什么区别,它们的一端连接着内核协议栈,而另一端的行为是什么取决于不同网络设备的驱动实现。

2.tun/tap 虚拟网络设备

TUN/TAP 虚拟网络设备一端连着协议栈,另外一端不是物理网络,而是另外一个处于用户空间的应用程序。也就是说,协议栈发给 TUN/TAP 的数据包能被这个应用程序读取到,当然应用程序能直接向 TUN/TAP 发送数据包。

一个典型的使用 TUN/TAP 网络设备的例子如下图所示:

network-device-tun-tap.jpg

上图中我们配置了一个物理网卡,IP 为18.12.0.92,而 tun0 为一个 TUN/TAP 设备,IP 配置为10.0.0.12。数据包的流向为:

  1. 应用程序 A 通过 socket A 发送了一个数据包,假设这个数据包的目的 IP 地址是 10.0.0.22
  2. socket A 将这个数据包丢给网络协议栈
  3. 协议栈根据本地路由规则和数据包的目的 IP,将数据包由给 tun0 设备发送出去
  4. tun0 收到数据包之后,将数据包转发给了用户空间的应用程序 B
  5. 应用程序 B 收到数据包之后构造一个新的数据包,将原来的数据包嵌入在新的数据包(IPIP 包)中,最后通过 socket B 将数据包转发出去

Note: 新数据包的源地址变成了 tun0 的地址,而目的 IP 地址则变成了另外一个地址 18.13.0.91.

  1. socket B 将数据包发给协议栈
  2. 协议栈根据本地路由规则和数据包的目的 IP,决定将这个数据包要通过设备 eth0 发送出去,于是将数据包转发给设备 eth0
  3. 设备 eth0 通过物理网络将数据包发送出去

我们看到发送给10.0.0.22的网络数据包通过在用户空间的应用程序 B,利用18.12.0.92发到远端网络的18.13.0.91,网络包到达18.13.0.91后,读取里面的原始数据包,再转发给本地的10.0.0.22。这就是 VPN 的基本实现原理。

使用 TUN/TAP 设备我们有机会将协议栈中的部分数据包转发给用户空间的应用程序,让应用程序处理数据包。常用的使用场景包括数据压缩、加密等功能。

Note: TUN 和 TAP 设备的区别在于,TUN 设备是一个虚拟的端到端 IP 层设备,也就是说用户空间的应用程序通过 TUN 设备只能读写 IP 网络数据包(三层),而 TAP 设备是一个虚拟的链路层设备,通过 TAP 设备能读写链路层数据包(二层)。如果使用 Linux 网络工具包 iproute2 来创建网络设备 TUN/TAP 设备 则需要指定 --dev tun--dev tap 来区分。

通俗例子 比如:由于疫情 你需要在家办公,当你需要去访问公司的内网的时候 正常来说 是访问不到的,但是当你连接了VPN后 ,VPN软件会在你的电脑里 创建一个 TUN 设备(可以想象为网卡) 然后它能接收到你的发往 公司的ip 段(172.17。。) 它会把请求转发给用户空间的VPN软件,VPN软件会根据你的VPN 配置 把目地地址改成你公司的外网地址 然后通过 网卡转发出去 就实现了 通过VPN访问 你公司的内网了。

3.veth pair 虚拟网络设备

veth虚拟网络设备的特点是 它会 成对出现,pair 英文就是成对的意思,也就是说 你创建 veth 的时候 它会创建一个对 veth设备,veth设备一段连着 Linux网络协议栈,另外一端 不是连物理网络,而是另外的一个 veth设备,成对的veth发送数据后会直接到另外一个veth 设备上去 ,而且每个veth 都可以设置IP 地址,并且 参与 三层IP网络路由过程

image-20220514082100790

ip link add veth0 type veth peer name veth1 #创建一个 veth pair 它是一对 分别是 veth0 和 veth1
ip addr add 20.1.0.10/24 dev veth0 #给veth 设备添加IP地址
ip addr add 20.1.0.11/24 dev veth1
ip link set veth0 up #设置设备启动 
ip link set veth1 up

此时通过 ifconfig 可以看到 两个虚拟设备,也可以通过 ip link show

veth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500   
        inet 20.1.0.10  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::4c36:f8ff:feee:2664  prefixlen 64  scopeid 0x20<link>
        ether 4e:36:f8:ee:26:64  txqueuelen 1000  (Ethernet)
        RX packets 14  bytes 1020 (1020.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 25  bytes 1930 (1.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 20.1.0.11  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::c4bd:37ff:fe62:3f2  prefixlen 64  scopeid 0x20<link>
        ether c6:bd:37:62:03:f2  txqueuelen 1000  (Ethernet)
        RX packets 25  bytes 1930 (1.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14  bytes 1020 (1020.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

此时去 ping 20.1.0.10 和 20.1.0.11 都是可以通的

[root@localhost ~]# ping 20.1.0.10
PING 20.1.0.10 (20.1.0.10) 56(84) bytes of data.
64 bytes from 20.1.0.10: icmp_seq=1 ttl=64 time=0.102 ms
64 bytes from 20.1.0.10: icmp_seq=2 ttl=64 time=0.066 ms
64 bytes from 20.1.0.10: icmp_seq=3 ttl=64 time=0.056 ms

此时通过 ip route 可以看到 路由信息

[root@localhost ~]# ip route
default via 10.0.2.2 dev enp0s3 proto dhcp metric 100
default via 192.168.56.1 dev enp0s8 proto static metric 101
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 metric 100

20.1.0.0/24 dev veth0 proto kernel scope link src 20.1.0.10 
20.1.0.0/24 dev veth1 proto kernel scope link src 20.1.0.11
4.场景总结
4.1 tun/tap

可以用来做VPN ,VPN的底层原理就是 使用 tun设备,还可以做数据压缩 和 数据加密等

4.2 veth pair

连接两个不同的网络命名空间(netns),连接docker容器,连接网桥(Bridge)等

总结

本篇主要介绍了 Linux 的2种 虚拟网络设备 ,其实还有不少其它的设备 bridge(虚拟交换机)等等。。

理解基础的虚拟网络设备能够帮助你更好的理解 Docker 底层网络 和 K8s 底层网络等

参考:https://morven.life/posts/networking-2-virtual-devices/

https://typesafe.cn/posts/linux-tun-tap/

欢迎大家访问 个人博客 Johnny小屋

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐