通用TUN/TAP设备驱动
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通用TUN/TAP设备驱动相关的知识,希望对你有一定的参考价值。
参考技术A 原文 Universal TUN/TAP device driverTUN/TAP为用户空间提供分组接收和传输。既可以看作一个Point-to-Point设备,也可以看做一个Ethernet设备。它从用户空间程序接收分组,而不是从物理媒介;将分组写入用户空间程序而不是通过物理媒介。
一个程序打开/dev/net/tun字符型文件,并向内核发出ioctl()来注册一个网络设备。根据选项,这个网络设备将显示为tunXX或者tapXX。当程序关闭文件描述符时,这个网络设备和所有对应的路由都将关闭。
用户空间程序read/write IP数据包(通过tun)还是以太网帧(通过tap),取决于选择的设备类型。正在使用哪一个取决于ioctl()设置的flag。
http://vtun.sourceforge.net/tun 下的软件包包含两个简单的示例,介绍如何使用tun和tap设备。两个示例的工作原理都像在两个网络接口之间的桥一样。
另外,最好的例子来源于VTun( http://vtun.sourceforge.net ) :))
创建设备节点:
设置权限:
驱动程序模块自动加载:
确保内核启用了“内核模块加载器” - 模块自动加载支持。 内核应该在第一次访问时加载它。
手动加载:
后一种方法,每次当你需要使用模块的时候,你都需要加载它。另一种方法将在你打开/dev/net/tun的时候自动加载。
设备的名称 char *dev 是具有格式的字符串(e.g. "tun%d"),也可以是任何有效的网络设备名称。注意,字符指针将会被真实网络设备名覆盖。
如果 IFF_NO_PI 标志没有被设置,每一帧格式如下:
从3.8版开始,Linux支持多队列tuntap,它可以使用多个文件描述符(队列)来并行发送或接收数据包。 设备分配与以前相同,如果用户想要创建多个队列,则必须使用IFF_MULTI_QUEUE标志多次调用具有相同设备名称的TUNSETIFF。
char *dev 是设备的名称, queues 是要创建的队列数, fds 用于存储和返回创建给调用者的文件描述符(队列)。 每个文件描述符都作为一个队列的接口,可以被用户空间访问。
引入了一个新的 ioctl(TUNSETQUEUE) 来启用或禁用队列。 当用 IFF_DETACH_QUEUE 标志调用它时,队列被禁用。 当用 IFF_ATTACH_QUEUE 标志调用它时,队列被启用。 通过 TUNSETIFF 创建队列后,队列默认启用。
fd是我们想要启用或禁用的文件描述符(队列),当enable为真时,我们启用它,否则我们禁用它
硬货 | 利用 Linux tap/tun 虚拟设备写一个 ICMP echo 程序
本文首发于我的公众号 CloudDeveloper(ID: cloud_dev),专注于干货分享,号内有大量书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫。
前面两篇文章已经介绍过 tap/tun 的原理和配置工具。这篇文章通过一个编程示例来深入了解 tap/tun 的程序结构。
01 准备工作
首先通过 modinfo tun
查看系统内核是否支持 tap/tun 设备驱动。
[[email protected] ~]# modinfo tun
filename: /lib/modules/3.10.0-862.14.4.el7.x86_64/kernel/drivers/net/tun.ko.xz
alias: devname:net/tun
alias: char-major-10-200
license: GPL
author: (C) 1999-2004 Max Krasnyansky <[email protected]>
description: Universal TUN/TAP device driver
retpoline: Y
rhelversion: 7.5
srcversion: 50878D5D5A0138445B25AA8
depends:
intree: Y
vermagic: 3.10.0-862.14.4.el7.x86_64 SMP mod_unload modversions
signer: CentOS Linux kernel signing key
sig_key: E4:A1:B6:8F:46:8A:CA:5C:22:84:50:53:18:FD:9D:AD:72:4B:13:03
sig_hashalgo: sha256
在 linux 2.4 及之后的内核版本中,tun/tap 驱动是默认编译进内核中的。
如果你的系统不支持,请先选择手动编译内核或者升级内核。编译时开启下面的选项即可:
Device Drivers => Network device support => Universal TUN/TAP device driver support
tap/tun 也支持编译成模块,如果编译成模块,需要手动加载它:
[[email protected] ~]# modprobe tun
[[email protected] ~]# lsmod | grep tun
tun 31665 0
关于以上的详细步骤,网上有很多教程,这里就不再赘述了。
https://blog.csdn.net/lishuhuakai/article/details/70305543
上面只是加载了 tap/tun 模块,要完成 tap/tun 的编码,还需要有设备文件,运行命令:
mknod /dev/net/tun c 10 200 # c表示为字符设备,10和200分别是主设备号和次设备号
这样在 /dev/net
下就创建了一个名为 tun 的文件。
02 编程示例
2.1 启动设备
使用 tap/tun 设备,需要先进行一些初始化工作,如下代码所示:
int tun_alloc(char *dev, int flags)
{
assert(dev != NULL);
struct ifreq ifr;
int fd, err;
char *clonedev = "/dev/net/tun";
if ((fd = open(clonedev, O_RDWR)) < 0) {
return fd;
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = flags;
if (*dev != '