OpenVPN的另一种部署模型是具有多个远程客户端的单个服务器,能够路由以太网流量。我们将此部署模型称为 具有tab设备的客户端/服务器模式。
tun和tap模式的主要区别在于使用的适配器类型。
tap适配器提供完整的虚拟以太网(第二层)接口,而tun适配器被大多数操作系统视为点对点(第三层)适配器。使用(virtual)以太网适配器连接的计算机可以形成单个广播域,这是某些应用程序所必需的。对于点对点适配器,这是不可能的。此外,请注意,并非所有操作系统都支持tap适配器。例如,iOS和Android都只支持tun设备。
在本章中,我们从基本的客户端/服务器设置开始,这与第四章Client/Server Mode with tun Devices中描述的基本设置非常相似。然而,存在一些细微的差异,我们将通过几个例子进行讨论。此外,tap模式支持桥接设置,其中常规网络适配器与虚拟tap适配器桥接。本主题将针对Linux和Windows操作系统进行详细描述。
本章将涵盖以下主题:
pf
启用客户端到客户端流量tap模式下OpenVPN的基本设置几乎与tun模式完全相同。在tap模式下,服务器配置文件中使用以下行:
xxxxxxxxxx
dev tap
而在tun模式下,我们使用的是以下行:
xxxxxxxxxx
dev tun
topology subnet
topology subnet
选项不是必需的,但提供了一种更合理的网络寻址方案,这将是OpenVPN未来版本的默认方案。
为了完整起见,我们首先创建服务器配置文件:
xxxxxxxxxx
proto udp
port 1194
dev tap
server 10.222.0.0 255.255.255.0
persist-key
persist-tun
keepalive 10 60
remote-cert-tls client
tls-auth /etc/openvpn/movpn/ta.key 0
dh /etc/openvpn/movpn/dh2048.pem
ca /etc/openvpn/movpn/movpn-ca.crt
cert /etc/openvpn/movpn/server.crt
key /etc/openvpn/movpn/server.key
user nobody
group nobody
verb 3
daemon
log-append /var/log/openvpn.log
我们将在本章和其他章节中重复使用此基本tap模式服务器配置文件。将此文件保存为 tap-udp-server.conf
,已被后续重复使用。
注意,topology subnet
选项被移除了,因为 topology
选项是tun特定选项。在tap模式中,服务器将始终向每一个客户端分配一个IP地址,并带有相应的网络掩码。
同样,我们创建客户端配置文件,该文件与第四章 Client/Server Mode with tun Devices 中的 basic-udp-client.conf
文件几乎相同:
xxxxxxxxxx
proto udp
port 1194
dev tap
client
remote openvpnserver.example.com
nobind
remote-cert-tls server
tls-auth /etc/openvpn/movpn/ta.key 1
ca /etc/openvpn/movpn/movpn-ca.crt
cert /etc/openvpn/movpn/client1.crt
key /etc/openvpn/movpn/client1.key
将文件保存为 tap-udp-client.conf
。同样,对于Windows客户端,创建配置文件 tap-udp-client-ovpn
。
启动OpenVPN服务器,并使用这些配置文件连接客户端。与基于tun的设置相比,服务器端连接日志显示了一些细微的差异,这些差异将在以下部分中突出显示:
xxxxxxxxxx
OpenVPN 2.3.6 x86_64-redhat-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [PKCS11] [MH] [IPv6] built on Dec 2 2014
library versions: OpenSSL 1.0.1e-fips 11 Feb 2013, LZO 2.03
[…]
TUN/TAP device tap0 opened
TUN/TAP TX queue length set to 100
do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0
/sbin/ip link set dev tap0 up mtu 1500
/sbin/ip addr add dev tap0 10.222.0.1/24 broadcast 10.222.0.255
GID set to nobody
UID set to nobody
UDPv4 link local (bound): [undef]
UDPv4 link remote: [undef]
MULTI: multi_init called, r=256 v=256
IFCONFIG POOL: base=10.222.0.2 size=253, ipv6=0
Initialization Sequence Completed
CLIENT_IP:60728 TLS: Initial packet from [AF_INET]CLIENT_IP:60728, sid=d4d7f1fd 988e4ff3
[…]
client1/CLIENT_IP:60728 PUSH: Received control message: 'PUSH_REQUEST'
client1/CLIENT_IP:60728 SENT CONTROL [client1]: 'PUSH_REPLY,route-gateway 10.222.0.1,ping 10,ping-restart 60,ifconfig 10.222.0.2 255.255.255.0' (status=1)
client1/CLIENT_IP:60728 MULTI: Learn: 8e:66:e4:43:35:a1 -> client1/CLIENT_IP:60728
服务器连接日志的最后一行实际上是最有趣的一行:MULTI: Learn
行显示服务器现在正在使用远程客户端的MAC地址将其与其他客户端区分开来,而在tun模式下,它可以仅依赖分配给客户端的IP地址。这是必要的,因为基于抽头的客户端也可以发送不使用IP地址的非IP流量。
当多个VPN客户端连接到服务器,它们之间不能相互通信。在tap模式和tun模式下都是如此。为了启用客户端到客户端之间的流量,可以使用以下两个选项:
client-to-client
。这允许OpenVPN在内部处理客户端到客户端的流量,绕过系统路由表以及系统防火墙/iptables规则。第一个选项是最快的选项,无论对配置方面还是性能方面。如果VPN客户端之间的流量没有限制,请将 client-to-client
行添加到 tap-udp-server.conf
文件中,并将其另存为 movpn-06-01-server.conf
,然后使用此配置文件重新启动OpenVPN服务器:
xxxxxxxxxx
$ openvpn --config movpn-06-01-server.conf
重新连接VPN客户端。第一个客户端会被分配IP地址 10.222.0.2,第二个客户端是 10.222.0.3。客户端之间可以互相ping通。
所有流量都会流经OpenVPN服务器,因此 client1
到 client2
的 ping
需要更长的时间。
如果VPN客户端通过高延迟网络连接,那么使用客户端/服务器型VPN将增加客户端之间发送流量的延迟。OpenVPN是一种客户端/服务器模式的VPN,大多数可用的商业VPN解放方案都是如此。存在一些对等VPN解决方案,但它们不在本书讨论范围。
client-to-client
选项的一个缺点是缺乏过滤。添加此选项后,允许所有客户端之间的所有流量,绕过系统防火墙/iptables规则。
允许流量在客户端之间流动的第二种方法是使用系统的路由表。在tun模式下,这很容易实现,但在使用tap模式时有点棘手。当 client1
希望访问 client2
时,它首先需要知道 client2
的MAC地址。ARP请求通过客户端的tap适配器发送,并到达OpenVPN服务器。OpenVPN服务器进程从其自己tap适配器转发ARP请求,并等待响应。但是响应需要来自连接到同一tap适配器的另一个VPN客户端。因此,ARP请求需要由OpenVPN服务器发送回所有连接的客户端。通常,ARP请求的重新发出不会完成,客户端到客户端的流量会失败。
在现代Linux内核(2.6.34+或具有back-ported选项的内核)上,可以为每个接口设置一个特殊的 proxy_arp_pvlan
标志。此标志指示Linux内核从ARP请求来自的同一接口重新发送ARP请求。正是这个标志时客户端到客户端流量正常工作所必需的。因此,我们通过设置这个标志,在不使用客户端到客户端选项的情况下,在tap模式下启用客户端到客户端的流量:
xxxxxxxxxx
# echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp_pvlan
注意:此系统标志只能在设置 tap0
适配器后设置。可以在启动OpenVPN之前创建tap适配器(参阅Bridging on Linux ),也可以在OpenVPN启动后设置标记。在这种情况下,可以使用 up
脚本自动设置,如第七章 脚本和插件 中所述。
当 client1
希望到达 client2
时,设置此标志的网络流量如下:
client1
从tap适配器发送ARP请求。tap0
适配器中转发出去。tap0
适配器。后者是由 proxy_arp_pvlan
标志引起的。client2
接收请求并做出回应。ARP回复现在被发送回OpenVPN服务器。client1
.client1
现在知道去哪能找到 client2
并且可以发送流量到 client2
。第二步允许我们过滤不同客户端之间的流量。可以添加过滤规则(如,使用iptables),只允许某些类型的流量,或者只允许特殊客户端之间的流量。例如,以下 iptables
规则将阻止第一个和第二个OpenVPN客户端之间的流量:
xxxxxxxxxx
# iptables -I FORWARD -i tap0 -o tap0 \
-s 10.222.0.2 -d 10.222.0.3 -j DROP
注意,通过阻止一个方向的流量,两个客户端无法相互连接。对于单向阻塞,需要更高级的iptables规则。
在Windows或Mac OS操作系统上似乎没有 proxy_arp_pvlan
标志的等效物。
使用此特殊内核标志的一个主要缺点是,它不会将VPN转换为单个以太网广播域。使用 proxy_arp_pvlan
标志,VPN客户端可以使用arp消息互相连接。但是,它们将不会接收来自其他客户端的广播流量。当使用 client-to-client
选项时,所有连接的VPN客户端都会自动接收彼此的广播消息,但过滤流量更难(我们将在下一节中详述)。
过滤OpenVPN客户端流量的第二种方法是使用OpenVPN内置的pf过滤器。OpenVPN Access Server也完全支持此筛选器,这是由OpenVPN Technologies公司提供的商业产品。与大多数防火墙相比,pf删选器支持是初级的,但功能齐全,在所有平台上都受支持。我们现在将介绍在OpenVPN的开源版本中使用此过滤器的步骤。这个例子只是作为概念证明;很明显,对于生产级服务,需要不同的方法和/或工具。
为了使用 pf
过滤器,必须使用OpenVPN的管理界面。这是通过以下配置文件实现的:
xxxxxxxxxx
proto udp
port 1194
dev tap
server 10.222.0.0 255.255.255.0
persist-key
persist-tun
keepalive 10 60
remote-cert-tls client
tls-auth /etc/openvpn/movpn/ta.key 0
dh /etc/openvpn/movpn/dh2048.pem
ca /etc/openvpn/movpn/movpn-ca.crt
cert /etc/openvpn/movpn/server.crt
key /etc/openvpn/movpn/server.key
user nobody
group nobody
verb 3
daemon
log-append /var/log/openvpn.log
client-to-client
management 127.0.0.1 12000 stdin
management-client-auth
management-client-pf
将此文件保存为 movpn-06-02-server.conf
然后启动OpenVPN服务器。OpenVPN服务器将会向你要一个(新的)管理密码。这个密码将用于验证所有连接到管理界面的访问;VPN客户端单独进行验证。management-client-pf
选项同时要求设置 management-client-auth
选项。这样做的缺点是,每个客户端都必须提供一个(伪造的)用户名和密码,并且必须使用管理界面在服务器端授予每个客户端访问权限。
客户端配置文件如下:
xxxxxxxxxx
proto udp
port 1194
dev tap
client
remote openvpnserver.example.com
nobind
remote-cert-tls server
tls-auth /etc/openvpn/movpn/ta.key 1
ca /etc/openvpn/movpn/movpn-ca.crt
cert /etc/openvpn/movpn/client1.crt
key /etc/openvpn/movpn/client1.key
auth-user-pass
将其保存为 movpn-06-02-client.conf
(或者Windows使用的 movpn-06-02-client.ovpn
)。
在服务器端,使用 telnet
首次启动管理界面:
xxxxxxxxxx
# telnet 127.0.0.1 12000
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
ENTER PASSWORD:
SUCCESS: password is correct
>INFO:OpenVPN Management Interface Version 1 -- type 'help' for more info
然后启动OpenVPN客户端。在客户端通过管理界面获得访问权限之前,与服务器的连接将不会完成。在管理界面中,你现在将看到以下内容:
xxxxxxxxxx
>CLIENT:CONNECT,0,0
>CLIENT:ENV,n_clients=0
>CLIENT:ENV,IV_VER=2.3.6
>CLIENT:ENV,IV_PLAT=linux
>CLIENT:ENV,IV_PROTO=2
[…]
获取所有 >CLIENT
行后,授权客户端连接。为此,需要客户端标识符(Client Identifier——CID)和密钥标识符(Key Identifier——KID)。它们是OpenVPN客户端连接时第一行 >CLIENT
上的参数。在这个例子中,CID和KID都是0。要授予此客户端访问权限,必须在管理界面中输入命令 client-auth-nt CID KID
:
xxxxxxxxxx
client-auth-nt 0 0
SUCCESS: client-auth command succeeded
>CLIENT:ESTABLISHED,0CLIENT:CONNECT,0,0
第一个OpenVPN客户端现在被授予访问权限。我们现在可以使用命令 client-pf CID
将访问控制规则应用于此客户端。这是一个多行命令。在第一行之后,我们首先指定允许此客户端访问的子网:
xxxxxxxxxx
[SUBNETS ACCEPT]
-10.0.0.0/8
我们授予客户端访问除 10.0.0.0/8 之外的所有子网权限。
然后,我们指定此客户端可以访问哪些客户端:
xxxxxxxxxx
[CLIENTS ACCEPT]
-client3
我们允许客户端联系除证书名称 /CN=client3
的客户端之外的所有其他VPN客户端。使用两个 END
语句,一个带括号,一个不带括号。我们关闭 client-pf
命令:
xxxxxxxxxx
client-pf 0
[SUBNETS ACCEPT]
-10.0.0.0/8
[CLIENTS ACCEPT]
-client3
[END]
END
SUCCESS: client-pf command succeeded
这个OpenVPN客户端现在可以访问服务器端的所有子网,除了 10.0.0.0/8,并且可以联系除 client3
之外的所有其他OpenVPN客户端。
使用这种方法有很多缺点,但它确实适用于所有平台。主要缺点如下:
pf
过滤器目前,开源版本的OpenVPN没有工具将这些命令发送到管理界面。然而,商业OpenVPN接入服务器软件提供了应用过滤规则所需的机制。
基于tap的配置的一个特殊用例是桥接。桥接(bridging)一词适用于操作系统将两个网络适配器桥接在一起的功能。当桥接两个(或多个)适配器时,在其中一个适配器上接收到的所有以太网流量都会转发到该网桥中的所有其他适配器。这使得将两个网段连接(桥接)在一起并使其看起来像是一个单一的以太网广播域称为可能。桥接的常见用例如下:
proxy-arp
设置通常可以实现相同的效果。桥接也有缺点,最明显的是性能损失。所有进入其中一个网桥接口的网络流量都会通过所哟其他接口复制出来。因此,很容易用于多播或广播流量使网桥过载。特别是在客户端使用高延迟或低带宽连接的VPN设置中(例如,酒店中的公路战士——road warriors in a hotel),这种性能损失会很快使OpenVPN设置无法使用。
还应注意到,桥接设置通常是不必要的。借助现代操作系统和文件共享协议,基于tun的设置可以以更少的努力和更高的性能实现相同的结果。
不幸的是,人们仍然普遍存在误解,认为需要桥接才能在OpenVPN设置上使用Windows文件共享。第五章 tun模式下的高级部署场景的“通过VPN启用文件共享”一节中,详细解释了如何使用基于tun的设置和WINS服务器实现文件共享。
在某些情况下,桥接设置仍然是可取或必要的。我们现在将展示如何在Linux和Windows平台上设置桥接的OpenVPN配置。
考虑以下网络环境:
客户端tap地址:192.168.122.128
服务器端LAN:192.168.122.0/24,服务器br0地址192.168.122.1
在服务器端,LAN适配器eth0和OpenVPN虚拟tap适配器之间使用网桥。在Linux上,这是通过在启动OpenVPN之前创建tap适配器来实现的。为此,需要安装系统包 bridge-utils
。步骤如下:
1、首先,我们创建一个脚本来启动网桥:
xxxxxxxxxx
br="br0"
tap="tap0"
eth="eth0"
br_ip="192.168.122.1"
br_netmask="255.255.255.0"
br_broadcast="192.168.122.255"
# Create the tap adapter
openvpn --mktun --dev $tap
# Create the bridge and add interfaces
brctl addbr $br
brctl addif $br $eth
brctl addif $br $tap
# Configure the bridge
ifconfig $tap 0.0.0.0 promisc up
ifconfig $eth 0.0.0.0 promisc up
ifconfig $br $br_ip netmask $br_netmask broadcast $br_broadcast
2、将此文件保存为movpn-bridge-start
并赋予可执行权限:
xxxxxxxxxx
# chmod 755 movpn-bridge-start
3、接下来启动网桥:
xxxxxxxxxx
# ./movpn-bridge-start
Mon Jan 5 18:40:02 2015 TUN/TAP device tap0 opened
Mon Jan 5 18:40:02 2015 Persist state set to: ON
4、现在,我们使用以下命令为桥接设置创建一个配置文件:
xxxxxxxxxx
tls-server
proto udp
port 1194
dev tap0 ## 这个 '0' 极其重要
server-bridge 192.168.122.1 255.255.255.0 192.168.122.128 192.168.122.200
remote-cert-tls client
tls-auth /etc/openvpn/movpn/ta.key 0
dh /etc/openvpn/movpn/dh2048.pem
ca /etc/openvpn/movpn/movpn-ca.crt
cert /etc/openvpn/movpn/server.crt
key /etc/openvpn/movpn/server.key
persist-key
persist-tun
keepalive 10 60
user nobody
group nobody
verb 3
daemon
log-append /var/log/openvpn.log
5、将其保存为 movpn-06-03-server.conf
。server-bridge
选项指定网络网关、子网掩码、池开头、池结尾。池中的地址用于分配给客户端。
上例中的 dev tap0
行对于桥接设置的工作至关重要。在启动OpenVPN之前,我们已经为桥接创建了tap适配器。为了使用此适配器,我们必须明确指定适配器的名称。否则,OpenVPN将在启动时创建一个新的非桥接适配器。
6、启动OpenVPN服务器,并且使用本章前面创建的 tap-udp-client.conf
配置文件启动客户端连接。在Linux客户端上,连接日志将显示如下:
xxxxxxxxxx
TUN/TAP device tap0 opened
do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0
/sbin/ip link set dev tap0 up mtu 1500
/sbin/ip addr add dev tap0 192.168.122.128/24 broadcast 192.168.122.255
Initialization Sequence Completed
客户端被从池的有效地址中分配了第一个地址 192.168.122.18。
7、最后,我们验证我们可以访问服务器端局域网上的主机:
xxxxxxxxxx
[client]$ ping -c 4 192.168.122.246
PING 192.168.122.246 (192.168.122.246) 56(84) bytes of data.
64 bytes from 192.168.122.246: icmp_req=1 ttl=64 time=287 ms
64 bytes from 192.168.122.246: icmp_req=2 ttl=64 time=289 ms
64 bytes from 192.168.122.246: icmp_req=3 ttl=64 time=285 ms
64 bytes from 192.168.122.246: icmp_req=4 ttl=64 time=287 ms
--- 192.168.122.246 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 285.397/287.496/289.568/1.570 ms
当OpenVPN服务器进程停止时,网桥并不会自动关闭。由于网桥是在OpenVPN本身启动之前创建的,因此网桥会一直存在,直到被手动拆除。以下命令停止并删除使用 movpn-start-bridge
命令创建的网桥:
xxxxxxxxxx
# ifconfig br0 down
# brctl delif br0 eth0
# brctl delif br0 tap0
# brctl delbr br0
# openvpn --rmtun --dev tap0
考虑以下网络环境:
客户端tap地址:192.168.3.34
服务器端LAN:192.168.3.0/24,服务器bridge接口地址为192.168.3.15
之前的网络布局和现在的网络布局之间的唯一区别是所使用的IP地址的选择。
在Windows上,OpenVPN TAP-Win适配器是在安装OpenVPN本身时安装的。通常,TAP-Win适配器的名称由操作系统分配,类似于Local Area Connection 4。同样,局域网所连接的以太网适配器的名称也将具有类似于Local Area Connection 2的名称。
为了清楚起见(和一些理智),我们想重命名VPN(TAP)接口:
1、首先我们去Network and Sharing Center 的Change adapter settings 。
2、使用右键点击TAP-Win适配器,选择 Rename,将其更名为 tapbridge
。
3、选择两个需要桥接的适配器,点击右键,选择 Bridge Connections 。
4、确认新建了一个 Network Bridge 适配器。
5、无需为网桥配置静态IP地址。Network Bridge 有自己的(虚拟)MAC地址,因此由服务器端局域网上的DHCP服务器分配自己的IP地址。
6、使用文本编辑器或写字板创建OpenVPN服务器配置文件:
xxxxxxxxxx
tls-server
proto udp
port 1194
dev tap
dev-node tapbridge ## == the name of the TAP-Win adapter
server-bridge 192.168.3.15 255.255.255.0 192.168.3.128 192.168.3.250
remote-cert-tls client
tls-auth "c://program files/openvpn/config/ta.key" 0
dh "c://program files/openvpn/config/dh2048.pem"
ca "c://program files/openvpn/config/movpn-ca.crt"
cert "c://program files/openvpn/config/server.crt"
key "c://program files/openvpn/config/server.key"
persist-key
persist-tun
keepalive 10 60
verb 3
将其保存为 movpn-06-04-server.ovpn
,配置文件的目录一般在 c:\Program Files\OpenVPN\config
。
Windows版本的OpenVPN的服务器配置文件类似于Linux的配置文件。主要区别在于证书和密钥文件的完整路径,以及使用关键字 dev
和 dev-node
指定TAP-WIN适配器的方式。另请注意,user/group
和 daemon/logging
选项已被删除。
7、启动OpenVPN服务器(使用提升的权限) :
xxxxxxxxxx
C:> cd \program files\openvpn\config
C:> ..\bin\openvpn --config movpn-06-04-server.ovpn
请注意,Windows上OpenVPN的命令行版本在外观和行为上几乎与Linux命令行版本完全相同。
8、当OpenVPN尝试设置VPN时,Windows防火墙将弹出安全警告。点击Allow Access以授予OpenVPN设置VPN的权限,
9、如果我们现在返回Adapter Settings屏幕,我们将看到LAN适配器eth0 和TAP-Win适配器tapbridge都是 Enable,并且状态为Bridged。
10、接下来,使用本章前面创建的 tap-udp-client.ovpn
配置文件连接Windows客户端。客户端将从可用地址池中分配第一个地址 192.168.3.128
。
11、最后,我们验证我们可以访问服务器端局域网上的主机。
12、在服务器上,按命令窗口中的F4功能键停止OpenVPN服务器进程。对于生产级设置,最好使用与OpenVPN一起安装的OpenVPN服务启动和停止OpenVPN。
在桥接设置中,可以将客户端进一步集成到服务器端网络中。在大多数网络中,DHCP服务器用于分配IP地址。通常,OpenVPN使用以下命令为其客户端分配IP地址:
xxxxxxxxxx
server 10.200.0.0 255.255.255.0
或者,使用以下命令:
xxxxxxxxxx
server-bridge 192.168.3.15 255.255.255.0 192.168.3.128 192.168.3.250
也可以使用外部DHCP服务器为OpenVPN客户端分配地址。要实现这一点,只需要删除 server-bridge
选项后的任何IP地址范围的规范,如以下配置文件所示:
xxxxxxxxxx
tls-server
proto udp
port 1194
dev tap0 ## the '0' is extremely important
server-bridge
remote-cert-tls client
tls-auth /etc/openvpn/movpn/ta.key 0
dh /etc/openvpn/movpn/dh2048.pem
ca /etc/openvpn/movpn/movpn-ca.crt
cert /etc/openvpn/movpn/server.crt
key /etc/openvpn/movpn/server.key
persist-key
persist-tun
keepalive 10 60
user nobody
group nobody
verb 3
daemon
log-append /var/log/openvpn.log
将其保存为 movpn-06-05-server.conf
然后启动OpenVPN服务器。
当客户端连接并使用DHCP请求IP时,该请求将被转发到服务器端局域网上的DHCP服务器。DHCP服务器分配一个地址,该地址通过OpenVPN服务器发送回客户端。
在OpenVPN客户端上,可以通过检查 vpn0
连接的IP地址来验证这一点。
也可以在DHCP服务器上检查DHCP客户端列表。
tcpdump和wireshark工具对于排除“几乎正常工作”的OpenVPN设置非常有用。Wireshark可用于Linux、Mac OS X和Windows。它可以用作命令行工具,但最常用的是基于GUI的版本。在大多数基于Unix/Linux的平台上,命令行工具tcpdump也是可用的。
我们现在将使用tcpdump和wireshark来查看基于窃听的VPN设置上的数据包流。
地址解析协议——Address Resolution Protocol,ARP,是所有网络上最基本的以太网类型之一。
ARP是不通过点对点链路传输的以太网协议的一个典型例子。物理层(layer 1)通常是系统之间的电或光连接。在VPN的情况下,隧道取代了物理连接。OSI模型的下一步是以太网层(layer 2)。ARP协议通常用于在这一层发现其他设备。
以太网是第二层网络协议,而点对点链路是第三层网络协议。
为了观察ARP流量,我们首先使用之前创建的配置文件 movpn-06-01-server.conf
启动OpenVPN服务器。然后我们将两个Linux客户端连接到服务器。成功建立所有连接后,我们在其中一个客户端上启动 tcpdump
:
xxxxxxxxxx
# tcpdump -nnel -i tap0
现在,我们从一个客户端向另一个客户端发送一个ping数据包,并查看 tcpdump
输出。
CIFS——Common Internet File Sharing,通用互联网共享,最初是一种专有协议,NetBEUI。对共享文件和打印机的支持是通过Novell的互联网分组交换(Internetwork Packet eXchange, IPX)协议实现的,后来又添加了TCP/IP。如今,Windows文件共享协议已经发展,仅通过TCP/IP支持。旧版本的Windows中仍然存在针对传统文件协议的支持,我们将使用这种传统支持来触发非IP流量。
首先,我们在TAP-Win适配器上安装并启用 NWLink IPX/SPX传输协议。然后,我们将Windows客户端连接到使用配置文件 movpn-06-01-server.conf
启动的OpenVPN设置。此配置启用了 client-to-client
,因此,所有连接的客户端都应该看到来自该客户端的所有以太网广播流量。
当Windows客户端成功连接到VPN服务器时,它将开始发送流量,以宣布其名称和其他Windows文件共享信息。它将尝试通过TCP/IP实现这一点,但也会使用IPX消息。
我们在第二个VPN客户端上使用Wireshark,并监视tap界面上的流量。下一个屏幕截图显示,Windows客户端WINDOWSXP确实通过TCP/IP发送广播NetBIOS流量。这些是具有源地址10.222.0.3和目标地址10.222.0.255的条目。后一个地址是我们设置的VPN的TCP/IP广播地址。我们还看到使用IPX协议广播流量。
IPX广播消息是以太网广播消息,但它们不是基于IP的。这表明,采用 client-to-client
的tap式OpenVPN设置确实在连接的客户端之间共享所有以太网流量,包括广播流量。
tun风格的VPN和tap风格的VPN之间有许多相似之处。本节主要讨论它们之间的差异。
这些差异大多数源于一个事实:即tun型VPN是一个非广播的点对点IP网络,而tap型网络提供了一个完整虚拟的、类似以太网的网络,支持广播。
简而言之,tun型网提供了第三层网络连接,而tap型网络几乎提供了第二层网络的所有功能。
特别是使用 topology subnet
选项时,基于tun的设备类似于基于非桥接tap的设置:
server 10.200.0.0 255.255.255.0
设置一个VPN包含服务器地址10.200.1/24。每个客户端将获取到/24 IP地址,从 10.200.0.2/24 开始。client-connect
脚本的参数存在一些细微的差异。当然,讨论这些差异要有趣得多。一些差异是显而易见的,但也有一些细微的差异,在设置VPN时可能会产生重大影响。
在第2层网络(即tap-style)中,相邻客户端可以通过使用ARP广播探测邻居的地址来相互连接。ARP广播允许客户端发现其他客户端的MAC地址。这允许客户端通过IP和非IP协议相互连接。 在第3层网络(tun-style)中,客户端只能通过使用IP地址相互连接。tun适配器的MAC地址永远不会透露给其他VPN客户端,甚至不会透露给OpenVPN服务器本身。因此,第3层网络分组比第2层网络分组稍短。在正常情况下,较长的第2层网络数据包不会对性能产生负面影响。
特别是在需要子网到子网(subnet-to-subnet)路由时,tun和tap之间存在一些显著差异。在tun型网络中,需要一个带有适当 iroute
语句的客户端配置文件,以允许VPN服务器访问驻留在客户端局域网上的客户端。例如,我们假设可以通过证书 CN=client1
的OpenVPN客户端访问子网 192.168.3.0/24。在OpenVPN服务器上,我们将添加一个名为 client1
的 client-config-dir
文件,其中包含一条语句:
xxxxxxxxxx
iroute 192.168.3.0 255.255.255.0
在服务器配置文件中,我们将添加一条系统路由:
xxxxxxxxxx
route 192.168.3.0 255.255.255.0
在tap型设置中, iroute
语句无效,服务器将忽略它。为了到达VPN客户后面的子网,必需在OpenVPN服务器上添加系统路由,网关指向客户端的VPN IP地址。让我们假设前面示例中的 client1
被分配了一个固定的IP地址。这可以通过使用CCD文件来实现:
xxxxxxxxxx
ifconfig-push 10.200.0.99 255.255.255.0
在服务器配置文件中,需要添加一条路由,以确保系统路由表知道可以通过客户端10.200.0.99访问子网 192.168.3.0/24:
xxxxxxxxxx
route 192.168.3.0 255.255.255.0 10.200.0.99
这远不如tun型的 route+iroute
选项机动(dynamic)。
在tun型的设置中,大多数流量都可以使用防火墙或iptables规则进行记录或过滤。如本章前面所示,在tap型设置中过滤OpenVPN客户端之间的流量则要困难得多。
第三层网不允许广播流量。这既是优点也是缺点。一些客户端/服务器应用程序依赖于使用广播流量在服务器和客户端之间进行通信。对于此类应用,需要一个tap型网络。
然而,广播流量也往往会污染网络。即使客户端上没有用户活动,操作系统也会不断发送广播流量以发现网络资源、邻居等。特别是当使用通用即插即用或苹果的Bonjour等协议时,会有很多隐藏的广播流量。对于通过低带宽网络连接到VPN的客户端,这可能会对性能产生严重影响。
tap型网络的关键特征是桥接能力。在第三层网络中无法进行桥接。
在某些罕见的情况下,此功能是绝对必要的,但应尽可能避免桥接设置。不使用桥接设置的主要原因是对性能的负面影响。如前所述,在桥接设置中,来自服务器端局域网的所有流量都通过VPN转发给所有客户端,反之亦然。当许多客户端通过低带宽网络连接时,这可能会导致整个网络在客户端甚至服务器端局域网上爬行。当服务器端局域网上的客户端试图发现网络上的可用资源(如,基于CIFS的网络中的文件共享或打印机)时,整个网络将充满广播流量。LAN客户端通常会等待连接到网络的所有机器(包括LAN和VPN)的响应,然后再提供对网络共享或打印机的访问。当许多VPN客户端正在连接和断开连接时,这可能会迅速导致不可接受的网络响应时间。
在本章中,我们探讨了基于tap的设置作为OpenVPN的替代部署模型的功能。我们讨论了一些例子,突出了这种设置的特点和缺点。特别关注桥接设置,因为在OpenVPN互联网支持论坛上发现了一些关于桥接模式的常见误解。
我们还看到,与tun模式相比,在tap模式下更难实现高级管理功能,例如过滤OpenVPN客户端之间的流量。
在下一章中,我们将看到如何使用脚本和插件来影响OpenVPN服务器向客户端分配IP地址的方式,以及许多其他功能。脚本和插件可以在点击模式和tun模式下使用。