This recipe is a continuation of the previous recipe. It will demonstrate how to set up a TAP-based connection in client or server mode using certificates. Using the client-to-client
directive, it will also enable different OpenVPN clients to contact each other. For TAP-based networks, this leads to some important side effects.
We use the following network layout:
Set up the client and server certificates using the first recipe from Chapter 2, Client-server IP-only Networks.
For this recipe, the server was running CentOS 6 Linux and OpenVPN 2.3.10; both clients were running Windows 7 64 bit and OpenVPN 2.3.10. For the server, keep the configuration file example3-1-server.conf
from the previous recipe at hand.
example3-1-server.conf
file: client-to-client
Save it as example-3-2-server.conf
.
[root@server]# openvpn --config example3-2-server.conf
iptables
masquerading rule:[root@server]# sysctl -w net.ipv4.ip_forward=1 [root@server]# iptables -t nat -I POSTROUTING -i tap+ -o eth0 -s 192.168.99.0/24 -j MASQUERADE
client proto udp remote openvpnserver.example.com port 1194 dev tap nobind remote-cert-tls server tls-auth "c:/program files/openvpn/config/ta.key" 1 ca "c:/program files/openvpn/config/ca.crt" cert "c:/program files/openvpn/config/client1.crt" key "c:/program files/openvpn/config/client1.key" verb 5
Save it as example-3-2-client1.ovpn
.
client proto udp remote openvpnserver.example.com port 1194 dev tap nobind remote-cert-tls server tls-auth "c:/program files/openvpn/config/ta.key" 1 ca "c:/program files/openvpn/config/ca.crt" cert "c:/program files/openvpn/config/client2.crt" key "c:/program files/openvpn/config/client2.key" verb 5
Save it as example-3-2-client2.ovpn
.
[WinClient1]C:> cd program filesopenvpnconfig [WinClient1]C:> ..inopenvpn --config example3-2- client1.ovpn
Start Client2 using the OpenVPN GUI:
As the private key file client2.key
is protected using a passphrase, we will be prompted for it:
We can now verify that the VPN connection is working by doing this. First, ping the server:
[WinClient1]C:> ping 192.168.99.1 Pinging 192.168.99.1 with 32 bytes of data: Reply from 192.168.99.1: bytes=32 time=24ms TTL=64 Reply from 192.168.99.1: bytes=32 time=25ms TTL=64
Then, ping the second client:
[WinClient1]C:> ping 192.168.99.3 Pinging 192.168.99.3 with 32 bytes of data: Reply from 192.168.99.3: bytes=32 time=49ms TTL=128 Reply from 192.168.99.3: bytes=32 time=50ms TTL=128
Notice the higher round-trip time.
[WinClient1]C:> ping -c 2 10.198.0.9 Pinging 10.198.0.9 with 32 bytes of data: Reply from 10.198.0.9: bytes=32 time=25ms TTL=63 Reply from 10.198.0.9: bytes=32 time=25ms TTL=63
Both clients connect to the OpenVPN server in the regular manner. The following directive is all that is needed for the clients to see each other:
client-to-client
Communication between the clients will still pass through the OpenVPN server, which explains the higher round-trip time for the ICMP packets. The flow of an ICMP (ping
) echo and reply is as follows:
As always, there are some caveats to watch out for.
All machines that are connected to a TAP-style network form a single broadcast domain. When client-to-client
is enabled, this means that all of the broadcast traffic from all the clients is forwarded to all other clients. Wireshark running on client2
indeed shows a lot of broadcast packets from client1
, all of which passed through the OpenVPN server. This can lead to a scalability problem when a large number of clients are connected.
In the current version of OpenVPN, it is not possible to filter the traffic between VPN clients when the client-to-client
directive is used. OpenVPN does have the capability for a filtering plugin, but this plugin is not maintained and requires extensive configuration.
A second method of filtering traffic between clients is to use the system's routing tables, in combination with a Linux kernel flag, proxy_arp_pvlan
. This flag is available in modern Linux kernels (2.6.34+ or kernels with back-ported options). This flag instructs the Linux kernel to resend the ARP request back out of the same interface from where it came. It is exactly this flag that is needed for client-to-client traffic to work without using the client-to-client
directive. Thus, in order to filter traffic, we first enable client-to-client traffic in tap mode by setting this flag:
# echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp_pvlan
We can then use iptables
command to filter traffic between clients.
18.118.166.106