Linux tun 设备介绍
tun 是一种虚拟的3层虚拟网络设备,同时它也是一个字符设备,字符设备意味着可以把它当做一个文件,可以使用文件API操作这个设备,例如 open/read/write,由于它同时也是一个网络设备,所以它也可以像一个网卡一样,从内核网络协议栈中收发报文。所以从它架构上来看,tun 设备的一端连接着应用程序,一端连接着网络协议栈,如下图所示:
从在系统中的表象来看,字符设备的文件类型是c,没有大小,但是有主次版本号:
1 | $ ls -alh /dev/net/tun |
tun 设备的创建是通过打开/dev/net/tun这个文件,然后使用ioctl系统调用对其进行clone。也可以使用 ip 命令来实现tun设备的创建:
ip tuntap add dev tun1 mod tun
新创建的 tun1 设备位于 /sys/class/net/ 目录中:
1 | $ ll /sys/class/net/tun1 |
删除使用如下命令:
ip tuntap del dev tun1 mod tun
ICMP 示例
如前文所述,tun设备的使用需要打开/dev/net/tun并对其clone之后才能进行使用,所以通用的创建tun设备有如下的步骤:
1 | int tun_alloc(char *dev, int flags) |
创建tun设备需要是root的用户,或者该应用程序需要具有CAP_NET_ADMIN权限,/dev/net/tun必须以读写方式打开,它是创建任何tun/tap虚拟接口的起点,因此也被称为克隆设备(clone device)。操作(open())后会返回一个文件描述符,但此时还无法与接口通信。下一步会使用一个特殊的ioctl()系统调用,该函数的入参为上一步得到的文件描述符,以及一个TUNSETIFF常数和一个指向描述虚拟接口的结构体指针。
tun_alloc 函数的两个参数中:
dev:指的是创建的tun设备的名称,如果*dev为'\0',则内核会尝试使用第一个对应类型的可用的接口,例如从tun0开始,如果tun0存在就为tun1;flags:用于指定虚拟设备的类型,通常为IFF_TUN或者IFF_TAP,分别代表tun或者tap设备。除此之外,还有一个IFF_NO_PI标志,可以与IFF_TUN或IFF_TAP配合使用。IFF_NO_PI会告诉内核不需要提供报文信息,即告诉内核仅需要提供"纯"IP报文,不需要其他字节。否则(不设置IFF_NO_PI),会在报文开始处添加4个额外的字节(2字节的标识和2字节的协议);
如果要完整的处理到达tun设备的ICMP请求,需要手动回响应:
1 | int main() |
完整的示例程序如下所示:
点击展开
1 |
|
将完整的源代码保存成文件tun.c,使用如下的命令进行编译:
gcc -o taptun tun.c
打开终端运行编译生成的可执行程序taptun可执行程序。然后打开另外一个终端,查询创建的tun0设备:
1 | $ ifconfig tun0 |
这个时候的tun0还未设置IP地址,可以使用如下的命令进行设置并启用:
ip a a 10.1.1.2/24 dev tun0
ip l s tun0 up
再次查看该设备,可以看到IP地址已经设置,并且处于启用状态:
1 | $ ifconfig tun0 |
创建设置并且设置IP以后,可以看到操作系统会自动添加一条路由,表示发往 10.1.1.0/24 这个网段的所有报文都会经 tun0 设备发出:
1 | $ route -n |
所以只要ping这个网段内的任一IP都会到达tun0设备,并且被我们的taptun应用程序收到并处理,例如:
1 | $ ping -c 1 10.1.1.10 |
应用程序将会有如下的输出:
1 | $ ./taptun |
参考链接
- IP packets
- IPv4 - Packet Structure
- ICMP Explained and Packet Format
- https://juejin.cn/post/7057833934947614750
- https://blog.51cto.com/u_11299290/5107265
- https://ctimbai.github.io/2019/03/01/tech/net/vnet/基于taptun写一个ICMP程序/
- https://www.zhengwenfeng.com/pages/143447/#应用程序通过tun设备获取ping数据包
- https://lxd.me/a-simple-vpn-tunnel-with-tun-device-demo-and-some-basic-concepts
- https://www.rectcircle.cn/posts/linux-net-virual-05-tunnel/#tun-tap-虚拟设备
- https://www.zhaohuabing.com/post/2020-02-24-linux-taptun/
- https://www.luozhiyun.com/archives/684
- https://blog.avdancedu.com/52f625ca/
- https://www.xzcoder.com/posts/network/05-simple-vpn.html#程序测试