Skip to content

Instantly share code, notes, and snippets.

@Akagi201
Created July 17, 2014 06:06
Show Gist options
  • Save Akagi201/6fc5181775ffa96eccc8 to your computer and use it in GitHub Desktop.
Save Akagi201/6fc5181775ffa96eccc8 to your computer and use it in GitHub Desktop.
  • TUN和TAP是virutal-network kernel devices.
  • TUN(network TUNnel) 模拟layer 3(network layer)设备, IP packets, 用于routing.
  • TAP(network tap) 模拟layer 2(link layer)设备, Ethernet frames, 用于创建 network bridge.
  • tun/tap驱动程序是Linux平台虚拟网卡驱动程序, 驱动加载后会建立网络接口tun0, 与其他网卡驱动不同的是, tun驱动并不会把到达的数据包发送出去, 而是会暂时存储于队列之中, 用户态进程可以通过read, write读写网络数据包, 实质上此驱动是一种把网络数据包直接定向至用户态进程的一种方式. 用户态进程充当网络的角色, 通过read接受网卡数据包, write发送数据包给网卡.

tun/tap驱动程序实现了虚拟网卡的功能, tun表示虚拟的是点对点设备, tap表示虚拟的是以太网设备, 这两种设备针对网络包实施不同的封装.

经过操作系统通过TUN/TAP device发出去的包, 被deliver到一个用户空间程序, 这个用户空间程序把他自己附属于到这个device上. 一个用户空间程序也可以发送包给一个TUN/TAP device. 在这种情况, TUN/TAP device deliver(或inject)这些包到操作系统的network stack, 因此, 仿真他们的接收来自一个外部源.

利用tun/tap驱动, 可以将tcp/ip协议栈处理好的网络分包传给任何一个使用tun/tap驱动的进程, 由进程重新处理后再发到物理链路中.

Tun/tap驱动程序工作原理

做为虚拟网卡驱动, Tun/tap驱动程序的数据接收和发送并不直接和真实网卡打交道, 而是通过用户态来转交. 在linux下, 要实现核心态和用户态数据的交互, 有多种方式: 可以通用socket创建特殊套接字, 利用套接字实现数据交互; 通过proc文件系统创建文件来进行数据交互; 还可以使用设备文件的方式, 访问设备文件会调用设备驱动相应的例程, 设备驱动本身就是核心态和用户态的一个接口, Tun/tap驱动就是利用设备文件实现用户态和核心态的数据交互.

从结构上来说, Tun/tap驱动并不单纯是实现网卡驱动, 同时它还实现了字符设备驱动部分. 以字符设备的方式连接用户态和核心态.

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

Tun/tap设备的工作过程:

Tun/tap设备提供的虚拟网卡驱动,从tcp/ip协议栈的角度而言,它与真实网卡驱动并没有区别。从驱动程序的角度来说,它与真实网卡的不同表现在tun/tap设备获取的数据不是来自物理链路,而是来自用户区,Tun/tap设备驱动通过字符设备文件来实现数据从用户区的获取。发送数据时tun/tap设备也不是发送到物理链路,而是通过字符设备发送至用户区,再由用户区程序通过其他渠道发送。

发送过程: 使用tun/tap网卡的程序经过协议栈把数据传送给驱动程序,驱动程序调用注册好的hard_start_xmit函数发送,hard_start_xmit函数又会调用tun_net_xmit函数,其中skb将会被加入skb链表,然后唤醒被阻塞的使用tun/tap设备字符驱动读数据的进程,接着tun/tap设备的字符驱动部分调用其tun_chr_read()过程读取skb链表,并将每一个读到的skb发往用户区,完成虚拟网卡的数据发送。

接收数据的过程: 当我们使用write()系统调用向tun/tap设备的字符设备文件写入数据时,tun_chr_write函数将被调用,它使用tun_get_user从用户区接受数据,其中将数据存入skb中,然后调用关键的函数netif_rx(skb) 将skb送给tcp/ip协议栈处理,完成虚拟网卡的数据接收。

应用

VPN

  • OpenVPN
  • FreeLAN
  • n2n
  • tinc
  • VTun
  • OpenSSH
  • CJDNS
  • ICMPTX
  • NSTX
  • HTun
  • coLinux
  • Hamachi
  • NeoRouter
  • VPN-X

虚拟机网络

  • Bochs
  • coLinux
  • Hercules(S/390 emulator)
  • Open vSwitch
  • QEMU / Kvm
  • User-mode Linux
  • VirtualBox

通过网络仿真连接真实的机器

  • ns-3

tutorial

Refs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment