社区应用 最新帖子 精华区 社区服务 会员列表 统计排行
  • 1235阅读
  • 0回复

Tun/tap虚拟网卡的基本原理

楼层直达
级别: 光盘初级
发帖
125
飞翔币
335
威望
272
飞扬币
3949
信誉值
0
一、Tun/tap虚拟网卡的基本原理
tun/tap驱动程序实现了虚拟网卡的功能,tun表示虚拟的是点对点设备,tap表示虚拟的是以太网设备,这两种设备针对网络包实施不同的封装。利用tun/tap驱动,可以将tcp/ip协议栈处理好的网络分包传给任何一个使用tun/tap驱动的进程,由进程重新处理后再发到物理链路中。开源项目openvpn和Vtun( http://vtun.sourceforge.net 都是利用tun/tap驱动实现的隧道封装。
使用tun/tap驱动
在linux 2.4内核版本及以后版本中,tun/tap驱动是作为系统默认预先编译进内核中的。在使用之前,确保已经装载了tun/tap模块并建立设备文件:
#modprobe tun
#mknod /dev/net/tun c 10 200

参数c表示是字符设备, 10和200分别是主设备号和次设备号。

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协议栈处理,完成虚拟网卡的数据接收。

tun/tap驱动很巧妙的将字符驱动和网卡驱动糅合在一起。
二、tun模式点对点设备隧道的ip地址分配原则
dev tun
该模式要求本地和异地终端ip地址必须在相同的子网255.255.255.252里,无论是c/s模式,还是点对点方式,都是这样的要求。如果没有满足,将出现错误。详细信息参见'openvpn --show-valid-subnets'选项。
Ifconfig 10.8.0.1.1 10.8.0.2 是正确的ip地址。因为他们在255.255.255.252这个子网内。如下所示:
Network(网络) :10.8.0.0/30
Broadcast(广播):10.8.0.3
HostMin(起IP) :10.8.0.1
HostMax(止IP) :10.8.0.2
Hosts/Net(主机):2

Ifconfig 10.8.0.3 10.8.0.4 时错误的ip地址,因为10.8.0.3是Network(网络) 10.8.0.0/30的广播地址,10.8.0.4是子网地址。如下所示:

Network(网络) :10.8.0.4/30
Broadcast(广播):10.8.0.7
HostMin(起IP) :10.8.0.5
HostMax(止IP) :10.8.0.6
Hosts/Net(主机):2

满足如上的列表入下所示:.
[1,2] [5, 6] [9,10] [13,14] [17, 18] [21, 22] [ 25, 26] [ 29, 30] [ 33, 34] [ 37, 38] [ 41, 42] [ 45, 46] [ 49, 50] [ 53, 54] [ 57, 58] [ 61, 62] [ 65, 66] [ 69, 70] [ 73, 74] [ 77, 78][ 81, 82] [ 85, 86] [ 89, 90] [ 93, 94] [ 97, 98] [101,102] [105,106] [109,110] [113,114] [117,118] [121,122] [125,126] [129,130] [133,134] [137,138] [141,142] [145,146] [149,150] [153,154] [157,158] [161,162] [165,166] [169,170] [173,174] [177,178] [181,182] [185,186] [189,190] [193,194] [197,198] [201,202] [205,206] [209,210] [213,214] [217,218] [221,222] [225,226] [229,230] [233,234] [237,238] [241,242] [245,246] [249,250] [253,254]

1、point-to-point模式举例:
one endpoint的配置文件如下所示:

remote 159.226.3.234
dev tun2
port 1196
ifconfig 10.3.0.1 10.3.0.2
tls-server
ca key/ca.crt
cert key/server.crt
key key/server.key # This file should be kept secret
dh key/dh1024.pem
ping 10
verb 3
mute 10

the other endpoint 的配置文件如下:

tls-client
remote 159.226.3.252:1196
port 1196
dev tun
ifconfig 10.3.0.2 10.3.0.1
ca ca.crt
cert client.crt
key client.key # This file should be kept secret
dh dh1024.pem
ping 10
verb 3
mute 10

2、c/s模式举例:
server一端配置文件如下:
port 1195
;proto tcp
proto udp
;dev tap
dev tun1
ca ./key/ca.crt
cert ./key/server.crt
key ./key/server.key # This file should be kept secret
#CRL文件的申明,被吊销的证书链,这些证书将无法登录
#crl-verify vpncrl.pem
dh ./key/dh1024.pem
mode server
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
;client-config-dir ccd
client-to-client
duplicate-cn
keepalive 10 120
#comp-lzo
# The maximum number of concurrently connected
# clients we want to allow.
max-clients 100
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
log openvpn.log
;log-append openvpn.log
verb 3
;mute 20


client端配置文件

client
dev tun
;proto tcp
proto udp
remote 159.226.3.252 1195
port 1196
resolv-retry infinite
nobind

;user nobody
;group nobody
# Try to preserve some state across restarts.
persist-key
persist-tun
tls-client
ca ca.crt
cert client.crt
key client.key
;comp-lzo
;pull
;float
# Set log file verbosity.
verb 3
# Silence repeating messages
;mute 20


三、TAP虚拟以太隧道模式
虚拟以太隧道模式,也分为点到点模式和C/S模式,该模式没有IP地址限制,可以连续使用,虚拟子网的大小可以随意指定。但是不能用真正的IP地址,要用private ip ,如果用真正的ip地址会发生冲突。

1、 point-to-point模式举例
我们选择网络为10.4.0.0 子网是255.255.255.0作为我们的虚拟vpn的子网。
我们假设:网络10.4.0.0,子网255.255.255.0是一个新的,不同的子网与你现在正在使用的。
在计算机A上创建配置文件config.ovpn
tls-client
remote 159.226.3.252
dev tap
ifconfig 10.4.0.2 255.255.255.0
ca ca.crt
cert client.crt
key client.key # This file should be kept secret
dh dh1024.pem
ping 10
verb 3
mute 10

在计算机B上创建配置文件config.ovpn
remote 159.226.3.234
dev tap1
ifconfig 10.4.0.1 255.255.255.0
tls-server
ca key/ca.crt
cert key/server.crt
key key/server.key # This file should be kept secret
dh key/dh1024.pem
ping 10
verb 3
mute 10
另外一个很重要的事情是:remote选项是真正的地址,不是虚拟的ip地址。在vpn开始之前你必须能够ping地址,remote选项指定的。vpn将尽力连接那个地址。如果你不能ping通它之前,openvpn也不能连接它。
remote 指定的是真实的,不是vpn的地址,然而ifconfig指定的是虚拟vpn地址。在remote地址从来不应该是ifconfig选项的子网的一部分。


2、 C/S模式举例

服务器端:
;local a.b.c.d
port 1194
;proto tcp
proto udp
dev tap
;dev tun

tls-server
ca ./key/ca.crt
cert ./key/server.crt
;crl-verify vpncrl.pem
key ./key/server.key
dh ./key/dh1024.pem

# mode server
server 10.9.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
;push "redirect-gateway"
;push "dhcp-option DNS 10.8.0.1"
;push "dhcp-option WINS 10.8.0.1"
client-to-client
duplicate-cn
keepalive 10 120
;comp-lzo
;max-clients 100
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
log openvpn.log
verb 3



客户端配置文件:

client
dev tap
port 1198
proto udp
remote 159.226.3.252 1194
resolv-retry infinite
nobind
user nobody
group nobody
persist-key
persist-tun
tls-client
ca ca.crt
cert client.crt
key client.key
;comp-lzo
verb 4
四、以太桥接模式
以上说明的是路由方式。路由和桥接是通过vpn连接系统的两种方式。路由模式配置比较简单,桥接模式需要安装第三方软件,建立桥,手工配置网络信息,安装比较复杂。
前面我们说了Openvpn有2种模式,一种是路由模式,不能使用真正的ip地址分配,需要用private ip address;另外一种模式是桥接模式,把局域网通过桥接隧道延伸到互联网中任何一台机器。桥接模式的客户端通过隧道,从单位局域网的DHCP服务器上租IP地址,该地址是从159.226.3.128/255.255.255.128子网中获取。
有两种方式可以从DHCP服务器上获取IP地址:
1、使用server-bridge指令,假设vpn客户端的地址池是子网159.226.3.128/255.255.255.128的部分,这个地址池必须不在正在使用的DHCP服务器管理的范围之内。假设想让OPENVPN使用159.226.3.247 ---159.226.3.250分配给连接的vpn客户端,这个指令如下写法:
server-bridge 159.226.3.252 255.255.255.128 159.226.3.247 159.226.3.249
2、另外一种方法是,vpn客户端从DHCP服务器得到它们的ip地址,这个DHCP服务器是管理这个局域网的IP地址。如下所示:
mode server
dev tap0

这两种方式都需要调整我们正在使用的DHCP服务器的配置。从效果来看,第二种方式比较好,DHCP服务器可以统一管理IP地址,但是DHCP服务器配置要做调整,因为,如果按照一般局域网中计算机分配IP地址,存在如下问题:
1、由于VPN客户端逻辑上在局域网内,但是实际上分布在互联网的任何位置,如果把与真正在局域网中的计算机区分开来,可以节省带宽和效率。
2、在DHCP服务器分配给VPN客户端IP地址时,连同网关、域名服务器和其他,这样就破坏了原有vpn客户机的路由信息和域名解析信息,无法连接到互联网上,解决的办法是,只传送ip地址和子网地址,无需传送其他信息。
解决的办法是,调整DHCP服务器的配置文件,参照如下:



beefcake:~# cat /etc/dhcp3/dhcpd.conf
## If hardware address begins with 00:FF, the client is an
## openvpn tap adapter, and we do not want to assign a
## default gateway or dns server. Assign then to a special
## subclass and configure a pool which does not hand out
## these parameters.

class "openvpn" {
match if substring (hardware, 1, 2) = 00:FF;
}
## end class declaration

## subnet for br0

authoritative;
subnet 172.16.0.0 netmask 255.255.255.0 {
always-broadcast on;
max-lease-time 3600;
default-lease-time 1800;
option domain-name "ezone.net";
option subnet-mask 255.255.255.0;

pool {
deny members of "openvpn";
range 172.16.0.150 172.16.0.254;
option routers 172.16.0.1;
option domain-name-servers 172.16.0.1;
option tftp-server-name "172.16.0.209";
}

pool {
allow members of "openvpn";
range 172.16.0.100 172.16.0.125;
}

}