tun/tap 是操作系统内核中的虚拟的网络设备,它是实现了对应的硬件网络设备的所有功能的软件。其中tap 虚拟的是以太网设备,tap 虚拟的是点对点设备。
对于tun/tap 与物理网卡的区别是
物理网卡,一端是连着物理网络(网线或者wifi),另外一端是连着网络协议栈
Tun/tap: 一端连着的是应用程序(通过字符设备文件/net/dev/tun),一段连着的是网络协议栈
工作流程图如下
从流程图可以看出tun/tap 设备和 物理设备的区别,主要是物理网卡的一端是连着物理网络,而tun/tap另外一端连着的是应用程序,因此,TCP/IP协议栈发送给tun/tap的数据包就可以转发到对应的应用程序,对应着应用程序通过虚拟网卡就可以把数据发送到TCP/IP协议栈。
对于虚拟网卡,目前有两种模式,即tun模式 和 tap 模式。他们有着共同的工作方式,只是他们在七层模型中工作在不同的层,对于tun设备来说,它是一个三层设备,它从dev/net/tun读取到IP设备包,写入的也是对应的IP数据包,所以他不能进行ARP请求以及以太网广播。对于tap设备来说,他工作在第二层,他接受的是MAC层的数据帧。从dev/net/tun 字符设备上读取到的也是数据帧。
在linux 创建以及删除对应的 tun/tap命令如下
#创建tun设备 tun0 为设备名称
ip tuntap add dev tun0 mod tun
# 查看设备
ip link show
#创建tap设备
ip tuntap add dev tap0 mod tap
#删除 tun
ip tuntap del dev tun0 mod tun
#删除tap
ip tuntap del dev tap0 mod tap
# 设置ip地址,并且将设备置为可用
ip address add dev tap0 168.123.1.5/24
ip link set dev tap0 up
此时你在主机ping 168.123.1.5 是可以ping通的,通过route –n
命令可以看到当前新增加了一个对应的路由规则
应用场景
VPN详细很多小伙伴都使用过吧,VPN就是基于tun实现的,
VPN 的工作原理,当你在远程办公时,打开VPN,VPN客户端会在你当前主机上创建一个TUN设备,TUN设备的一头连着VPN客户端,一头连着网络协议栈,假设你的公司的内网的ip地址是172.13.2.44,此时会在系统中存在一条和上图相似的路由规则,会将对应的报文发到 tun0 对应的字符设备上,VPN通过读取字符设备上的数据获取到对应的请求报文,通过改写其报文以及对应的数据,将报文通过物理网卡在转发到对应的VPNserever
Veth pair 虚拟网络设备
Veth虚拟网络设备是成对出现的网络设备,有意思的是,当你创建一个veth 时候,此时会自动创建对端的veth 设备,并且这两个veth 设备 是相连的,像不像 一根网线?
Veth 和 tun 的区别如下图
可以通过如下命令对veth进行处理
#创建 一个veth piar 名称分别是veth0 和 veth1
ip link add veth0 type veth peer name veth1
# 分别给 两个设备设置对应的ip地址
ip addr add 20.1.0.10/24 dev veth0
ip addr add 20.1.0.11/24 dev veth1
# 启动对应的设备
ip link set veth0 up
ip link set veth1 up
#此时通过ifconfig 或者 ip link show 可以查看到对应的设备。并且可以ping通
作用: 我的理解是它可以当作一根网线,在进行虚拟设备连接的时候,可以将不同的设备联通,比如 虚拟网卡和 网桥进行连接。
如下可以做个实验,创建一组veth ,分别在ns0 和 ns1 中。然后测试对应的连通性
ip netns add ns0
ip netns add ns1
ip link add veth0 type veth peer name veth1
ip netns exec ns0 ip addr add 172.0.0.1/24 dev veth0
ip netns exec ns1 ip addr add 172.0.0.2/24 dev veth1
ip netns exec ns0 ip link set veth0 up
ip netns exec ns1 ip link set veth1 up
执行
ip netns ns0 ping 172.0.0.2
可以查看当前网络是通的
网桥
网桥这个名字很形象,在网络中的一个桥,他的作用和物理交换机相同。你可以简单地理解就是它可以联通两个局域网,会自动决定包走向哪一个局域网。比如如果ip地址不是一个网络段的时候,通过当前网桥就可以将两个不同ip段的物理设备连接起来。网桥一般工作在数据链路层,根据MAC地址来进行转发帧。
在centos7 中可以通过brctl 命令来操作网桥。其他的版本可以通过安装bridge-utils 来操作。
# 创建一个网桥
brctl addbr br1
# 添加一个设备到网桥
brctl addif br1 eth0
# 显示当前存在的网桥以及其所连接的 网络设备
brctl show
#启动网桥
ip link set br1 up
#删除网桥
brctl delbr br1
还记得讲解veth 得时候,我们通过veth 将两个命名空间的主机连接到了一起,但是当随着网络设备增多,不同的网络想要联通,最终会出现很复杂得网络拓扑结构。一旦出现问题排查起来就很麻烦(你可以理解为 局域网很多主机,都通过网线之间连接才能进行访问)
访问方式如下,左边是基于veth 实现的联通,右边是基于网桥实现得联通
通过借助veth 对 将其一端连到对应的虚拟设备上,另外一端连到 对用的 网桥上。从而实现网络拓扑简单化。
现在假设我们有三个网络空间ns0,ns1,ns2。然后通过网桥br0 将其连通
#添加三个namespace
ip netns add ns0
ip netns add ns1
ip netns add ns2
# 创建网桥并启动
brctl addbr br0
ip link set br0 up
# 增加三对veth
ip link add veth0 type veth peer name veth0-br
ip link add veth1 type veth peer name veth1-br
ip link add veth2 type veth peer name veth2-br
# 将其中的一端移到对应的namespace中
ip link set veth0 netns ns0
ip link set veth1 netns ns1
ip link set veth2 netns ns2
# 分别启动对应的veth 并且配置地址
ip netns exec ns0 ip link set lo up
ip netns exec ns0 ip addr add 172.168.1.1/24 dev veth0
ip netns exec ns0 ip link set veth0 up
ip netns exec ns1 ip link set lo up
ip netns exec ns1 ip addr add 172.168.1.2/24 dev veth1
ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip link set lo up
ip netns exec ns2 ip addr add 172.168.1.3/24 dev veth2
ip netns exec ns2 ip link set veth2 up
# 将veth 另一端挂在到对应的网桥上
ip link set veth0-br up
ip link set veth1-br up
ip link set veth2-br up
brctl addif br0 veth0-br
brctl addif br0 veth1-br
brctl addif br0 veth2-br
执行
ip netns exec ns0 ping 172.168.1.2 发现当前网络已经通了