linux Tun/Tap 原理

469 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

image.png

tun0是一个Tun/Tap虚拟设备,从上图中可以看出它和物理设备eth0的差别,它们的一端虽然都连着 协议栈,但另一端不一样,eth0的另一端是物理网络,这个物理网络可能就是一个交换机,而tun0的 另一端是一个用户层的程序,协议栈发给tun0的数据包能被这个应用程序读取到,并且应用程序能直 接向tun0写数据。

这里假设eth0配置的IP是10.32.0.11 (外网地址),而tun0配置的IP是192.168.3.11 (内网地址). 这里列举的是一个典型的tun/tap设备的应用场景,发到192.168.3.0/24网络的数据通过程序B这个 隧道,利用10.32.0.11发到远端网络的10.33.0.1,再由10.33.0.1转发给相应的设备,从而实现 VPN。

下面来看看数据包的流程:

  1. 应用程序A是一个普通的程序(比如是一个浏览器想通过vpn访问内网),通过socket A发送了一个数据包,假设这个数据包的目的IP地址是192.168.3.1 (内网地址)

  2. socket将这个数据包丢给协议栈

  3. 协议栈根据数据包的目的IP地址,匹配本地路由规则,知道这个数据包应该由tun0出去,于是将数据包交给tun0

  4. tun0收到数据包之后,发现另一端被进程B打开了,于是将数据包丢给了进程B

  5. 进程B收到数据包之后,做一些跟业务相关的处理,然后构造一个新的数据包,将原来的数据包嵌入在新的数据包中,最后通过socket B将数据包转发出去,这时候新数据包的源地址变成了eth0的地址,而目的IP地址变成了一个其它的地址,比如是10.33.0.1.

  6. socket B将数据包丢给协议栈

  7. 协议栈根据本地路由,发现这个数据包应该要通过eth0发送出去,于是将数据包交给eth0

  8. eth0通过物理网络将数据包发送出去

10.33.0.1收到数据包之后,会打开数据包,读取里面的原始数据包,并转发给本地的 192.168.3.1,然后等收到192.168.3.1的应答后,再构造新的应答包,并将原始应答包封装在里 面,再由原路径返回给应用程序B,应用程序B取出里面的原始应答包,最后返回给应用程序A