tun/tap 驱动程序实现了虚拟网卡的功能,tun表示虚拟的是点对点设备,tap表示虚拟的是以太网设备,这两种设备针对网络包实施不同的封装。利用tun/tap 驱动,可以将tcp/ip协议栈处理好的网络分包传给任何一个使用tun/tap驱动的进程,由进程重新处理后再发到物理链路中。
开源项目openvpn (http://openvpn.sourceforge.net)和Vtun(http://vtun.sourceforge.net)都是利用tun/tap驱动实现的隧道封装。
一. Tun/Tap驱动程序工作原理
在linux下,要实现内核空间和用户空间数据的交互,有多种方式:可以通用socket创建特殊套接字,利用套接字实现数据交互;通过proc文件系统创建文件来进行数据交互;还可以使用设备文件的方式,访问设备文件会调用设备驱动相应的例程,设备驱动本身就是内核空间和用户空间的一个接口,Tun/tap驱动就是利用设备文件实现用户空间和内核空间的数据交互。
用户空间的设备节点/dev/net/tun用于读写TUN/TAP设备,内核中TUN/TAP设备在发送数据包时,将数据包发送到与/dev/net/tun文件描述符相关联的套接口,用户空间就可从设备节点读取数据。用户空间程序向/dev/net/tun文件描述符写入数据时,TUN/TAP驱动调用内核的数据包接收函数(如netif_rx)将接收到的数据包送入网络协议栈,就像数据包是从物理网络中接收的一样。
Linux内核的TUN/TAP虚拟设备,不同于内核的其它设备,其发送和接收数据包都在网络协议栈内部完成,发送的数据包并不会离开协议栈进入到物理网络中,同样,也不会接收到从物理网络中进入协议栈的数据包。
|-----------| |--------------------------| | |--------------------------| |-----------|
| | | | | | | | |
| apps | | |---- tunnel ----| | | | |---- tunnel ----| | | apps |
| | | | | | | | | | | | |
|-----------| |------------| |--------| | |--------| |------------| |-----------|
192.168.1.0/24 |/dev/net/tun| | socket | | | socket | |/dev/net/tun| 192.168.1.0/24
|------------|----|--------| | |--------|----|------------|
| |
|----19.1.1.0/24---|
---------------------------------------------------------------------------------------------------
Linux内核网络协议栈 (ip route add 0.0.0.0/0 dev tun0)
图中左侧隧道处理程序从/dev/net/tun文件描述符读取网络应用发出的数据包,经过处理,比如加密,之后通过套接口发往远端(19.1.1.0网络)。图中右侧隧道处理程序通过套接口接收到数据包之后,经过处理,比如解密,之后写入/dev/net/tun文件描述符中,网络应用程序将从内核中接收到原始的数据包。当右侧网络应用回复数据包时,又会沿着原路返回左侧应用。
从结构上来说,Tun/tap驱动并不单纯是实现网卡驱动,同时它还实现了字符设备驱动部分。以字符设备的方式连接用户空间和内核空间。下面是示意图:
Tun/tap 驱动程序中包含两个部分,一部分是字符设备驱动,还有一部分是网卡驱动部分。利用网卡驱动部分接收来自TCP/IP协议栈的网络分包并发送或者反过来将接收到的网络分包传给协议栈处理,而字符驱动部分则将网络分包在用户空间和内核空间之间传送,模拟物理链路的数据接收和发送。Tun/tap驱动很好的实现了两种驱动的结合。
二、Tun/Tap网卡创建
1.确认内核是否支持tun/tap
[root@hunterfu]# modinfo tun
filename: /lib/modules/2.6.34.7-56.fc13.i686.PAE/kernel/drivers/net/tun.ko
alias: char-major-10-200
license: GPL
author: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
description: Universal TUN/TAP device driver
srcversion: 880DE258930FE60D765B735
depends:
vermagic: 2.6.34.7-56.fc13.i686.PAE SMP mod_unload 686
2. 加载内核模块
# modprobe tun
# lsmod | grep tun
tun 10548 1
执行以上命令后,出现如上输出,说明模块加载成功。
3.创建和配置虚拟网卡
确认是否有tunctl命令,如果没有通过yum安装即可。
# yum install tunctl
创建虚拟网卡设备
[root@hunterfu ~]# tunctl -t tap0 -u root
设置虚拟网卡
# ifconfig tap0 192.168.0.1 netmask 255.255.255.0 promisc
经过如上操作后,虚拟网卡已经建立和配置好了。
参考: