linux下TUN/TAP虚拟网卡的使用

在计算机网络中,TUN与TAP是操作系统内核中的虚拟网络设备。不同于普通靠硬件网路板卡实现的设备,这些虚拟的网络设备全部用软件实现,并向运行于操作系统上的软件提供与硬件的网络设备完全相同的功能。
TAP 等同于一个以太网设备,它操作第二层数据包如以太网数据帧。TUN模拟了网络层设备,操作第三层数据包比如IP数据封包。
操作系统通过TUN/TAP设备向绑定该设备的用户空间的程序发送数据,反之,用户空间的程序也可以像操作硬件网络设备那样,通过TUN/TAP设备发送数据。在后种情况下,TUN/TAP设备向操作系统的网络栈投递(或“注入”)数据包,从而模拟从外部接受数据的过程。
服务器如果拥有TUN/TAP模块,就可以开启VPN代理功能。

tun/tap 驱动程序实现了虚拟网卡的功能,tun表示虚拟的是点对点设备,tap表示虚拟的是以太网设备,这两种设备针对网络包实施不同的封装。利用tun/tap 驱动,可以将tcp/ip协议栈处理好的网络分包传给任何一个使用tun/tap驱动的进程,由进程重新处理后再发到物理链路中。
开源项目open (http://open.sourceforge.net)和Vtun(http://vtun.sourceforge.net)都是利用tun/tap驱动实现的隧道封装。


Tun Tap区别

    现在统一的说法是:
    TUN是点对点的三层设备,工作在IP层,处理IP分组;
    TAP是虚拟以太网设备,工作在第二层,处理以太网帧;

    
    而以下查得的资料也印证了这一点:
    摘自Universal TUN/TAP device driver的FAQ:
    The TUN is Virtual Point-to-Point network device.TUN driver was designed as low level kernel support for IP tunneling.
    The TAP is a Virtual Ethernet network device.TAP driver was designed as low level kernel support for Ethernet tunneling.
    TUN works with IP frames. TAP works with Ethernet frames
    摘自OpenVPN的FAQ:The difference between a tun and tap device is this: a tun device is a virtual IP point-to-point device and a tap device is a virtual ethernet device.
    
    其实这只是一面,说的很笼统,下面看一些更多的不同:
    1、设备号大不同。
    TUN 设备号是10 200,是字符设备下的misc设备,在2.6内核的miscdevice.h中定义的TUN_MINOR(从设备号)也是200;而TAP的是36 16,字符设备的netlink支持。
    参见device-list(2008-3):
    http://www.lanana.org/docs/device-list/devices-2.6+.txt
    
    2、显然,设备号的不同导致了文件节点的不同:
    TUN:/dev/net/tun
    TAP:/dev/tap0
    但是Universal TUN/TAP device driver的似乎是/dev/tun的类型,仔细发现这是在2.4内核之前的,在2.6以后,TUN设备就会对应于文件/dev/net/tun。


    3、补充一下,从其他资料偶尔看到了:

    TAP:子网掩码是/24,255.255.255.0,对应以太网设备

    TUN:子网掩码是/30,255.255.255.252,点对点设备。

    最后,在VTUN源代码咋实现open设备的打开时,TAP和TUN也是分开的,好像有两个TUN,一个是/dev/tun的节点(不包含),一个是/dev/net/tun(包含)。前者看来是为了2.4的核而设置的。


    总结一下吧(主要是TUN设备的困惑,TAP就没有):
    2.4的核:TUN 设备号是36 16+,文件节点:/dev/tun0
    2.6的核:TUN 设备号是10 200,文件节点:/dev/net/tun

补充一下,其实具体是TUN或者是TAP,都不是在open打开设备的文件节点时就确定的。文件节点只是内核提供给用户的接口而已,应用程序需要ioctl设置自己的虚拟网络设备的工作模式是TUN还是TAP。

  所以上面第二点的理解,需要变通一下!


Tun/Tap驱动程序工作原理

做为虚拟网卡驱动,Tun/Tap驱动程序的数据接收和发送并不直接和真实网卡打交道,他在Linux内核中添加了一个TUN/TAP虚拟网络设备的驱动程序和一个与之相关连的字符设备 /dev/net/tun,字符设备tun作为用户空间和内核空间交换数据的接口。当内核将数据包发送到虚拟网络设备时,数据包被保存在设备相关的一个队列中,直到用户空间程序通过打开的字符设备tun的描述符读取时,它才会被拷贝到用户空间的缓冲区中,其效果就相当于,数据包直接发送到了用户空间。通过系统调用write发送数据包时其原理与此类似。

在linux下,要实现内核空间用户空间数据的交互,有多种方式:可以通用socket创建特殊套接字,利用套接字实现数据交互;通过proc文件系统创建文件来进行数据交互;还可以使用设备文件的方式,访问设备文件会调用设备驱动相应的例程。设备驱动本身就是内核空间用户空间的一个接口,Tun/tap驱动就是利用设备文件实现用户空间内核空间的数据交互。

从结构上来说,Tun/tap驱动并不单纯是实现网卡驱动,同时它还实现了字符设备驱动部分。以字符设备的方式连接用户空间和内核空间。下面是示意图:


linux下TUN/TAP虚拟网卡的使用_第1张图片

Tun/tap 驱动程序中包含两个部分,一部分是字符设备驱动,还有一部分是网卡驱动部分。利用网卡驱动部分接收来自TCP/IP协议栈的网络分包并发送或者反过来将接收到的网络分包传给协议栈处理,而字符驱动部分则将网络分包在用户空间和内核空间之间传送,模拟物理链路的数据接收和发送。Tun/tap驱动很好的实现了两种驱动的结合。


Tun/Tap网卡创建

1. 确认内核是否支持tun/tap

  • 确认内核是否有tun模块

      [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 
      description:    Universal TUN/TAP device driver
      srcversion:     880DE258930FE60D765B735
      depends:        
      vermagic:       2.6.34.7-56.fc13.i686.PAE SMP mod_unload 686 
    


  • 加载内核模块 -

      [root@hunterfu ~]#  modprobe tun
      [root@hunterfu ~]# lsmod | grep tun
      tun                    10548  1 
    
    执行以上命令后,出现如上输出,说明模块加载成功


2. 创建和配置虚拟网卡

  • 确认是否有tunctl命令,如果没有通过yum安装即可

      [root@hunterfu ~]# yum install tunctl
    


  • 创建虚拟网卡设备

      [root@hunterfu ~]# tunctl -t tap0 -u root
    


  • 设置虚拟网卡

      [root@hunterfu ~]# ifconfig tap0 192.168.0.1  netmask 255.255.255.0 promisc
    
    经过如上操作后,虚拟网卡已经建立和配置好了。


3. 作为系统服务随系统自动启动创建虚拟网卡

  • 编写配置脚本(符合chkconfig规范)

      [root@hunterfu ~]# cat /etc/init.d/config_tap 
      #!/bin/bash
      #
      # config_tap          Start up the tun/tap virtual nic
      #
      # chkconfig: 2345 55 25
      
      USER="root"
      TAP_NETWORK="192.168.0.1"
      TAP_DEV_NUM=0
      DESC="TAP config"
      
      do_start() {
        if [ ! -x /usr/sbin/tunctl ]; then
          echo "/usr/sbin/tunctl was NOT found!"
          exit 1
        fi
        tunctl -t tap$TAP_DEV_NUM -u root
        ifconfig tap$TAP_DEV_NUM ${TAP_NETWORK}  netmask 255.255.255.0 promisc
        ifconfig tap$TAP_DEV_NUM
      }
      
      do_stop() {
        ifconfig tap$TAP_DEV_NUM down 
      }
      do_restart() {
        do_stop
        do_start
      }
      check_status() {
        ifconfig tap$TAP_DEV_NUM 
      }
      
      case $1 in 
        start)    do_start;;
        stop)     do_stop;;
        restart)  do_restart;;
        status)
                  echo "Status of $DESC: "
                  check_status
                  exit "$?"
                  ;;
        *)
      	echo "Usage: $0 {start|stop|restart|status}"
      	exit 1 
      esac
    
    可以根据具体需求修改此脚本


  • 加入到系统服务中

      [root@hunterfu ~]# chkconfig --add config_tap 
      [root@hunterfu ~]# chkconfig --level 345 config_tap on
    

  • 操作完成后,就可以像其他标准服务一样,通过service config_tap start来进行创建和启动操作

http://wushank.blog.51cto.com/3489095/1306849
http://blog.csdn.net/wangxing1018/article/details/3510118

你可能感兴趣的:(网络)