This recipe will demonstrate how to set up server-side routing in client or server mode. With this setup, the OpenVPN client will be able to reach all the machines behind the OpenVPN server.
Compared to the previous recipe, this recipe contains extra settings that are often used in production environments, as well as OpenVPN 2.1-specific features to make use of linear
addresses (topology subnet
).
The configuration files used in this recipe are useful building blocks for other recipes throughout this book, hence, they are named as basic-udp-server.conf
, basic-udp-client.conf
, and so on.
We use the following network layout here:
This recipe uses the PKI files created in the first recipe of this chapter. Install OpenVPN 2.1 on two computers. For this recipe, the server computer was running CentOS 5 Linux and OpenVPN 2.1.1 and the client was running Fedora 13 Linux and OpenVPN 2.1.1.
- Create the server configuration file:
proto udp port 1194 dev tun server 192.168.200.0 255.255.255.0 ca /etc/openvpn/cookbook/ca.crt cert /etc/openvpn/cookbook/server.crt key /etc/openvpn/cookbook/server.key dh /etc/openvpn/cookbook/dp024.pem tls-auth /etc/openvpn/cookbook/ta.key 0 persist-key persist-tun keepalive 10 60 push "route 10.198.0.0 255.255.0.0" topology subnet user nobody group nobody daemon log-append /var/log/openvpn.log
Then save it as
basic-udp-server.conf
. Note that in some Linux distributions, the groupnogroup
is used instead ofnobody
. - Copy over the
tls-auth
secret key file from the/etc/openvpn/cookbook/keys
directory:[root@server]# cp keys/ta.key ta.key
- And start the server:
root@server]# openvpn --config basic-udp-server.conf
- Make sure IP-traffic forwarding is enabled on the server:
[root@server]# sysctl -w net.ipv4.ip_forward=1
- Next, create the client configuration file:
client proto udp remote openvpnserver.example.com port 1194 dev tun nobind ca /etc/openvpn/cookbook/ca.crt cert /etc/openvpn/cookbook/client1.crt key /etc/openvpn/cookbook/client1.key tls-auth /etc/openvpn/cookbook/ta.key 1 ns-cert-type server
Save it as
basic-udp-client.conf
. - Transfer the
tls-auth
secret key file,ta.key
, to the client machine using a secure channel, such asscp
:[root@client]# scp \ openvpnserver:/etc/openvpn/cookbook/keys/ta.key .
- Start the client:
[root@client]# openvpn --config basic-udp-client.conf OpenVPN 2.1.1 x86_64-redhat-linux-gnu [SSL] [LZO2] [EPOLL] [PKCS11] built on Jan 5 2010 NOTE: OpenVPN 2.1 requires '--script-security 2' or higher to call user-defined scripts or executables Control Channel Authentication: using '/etc/openvpn/cookbook/ta.key' as a OpenVPN static key file UDPv4 link local: [undef] UDPv4 link remote: 194.171.96.27:1194 [openvpnserver] Peer Connection Initiated with 194.171.96.27:1194
- Add a route to the server-side gateway
gateway1
so that all VPN traffic is sent back to the VPN server. In this recipe, we use a router that understands a Linuxip route
like syntax:[gateway1]> ip route add 192.168.200.0/24 via 10.198.1.1
After the VPN is established, verify that we are able to ping a machine on the remote server LAN:
[client]$ ping -c 2 10.198.0.10
PING 10.198.0.10 (10.198.0.10) 56(84) bytes of data.
64 bytes from 10.198.0.10: icmp_seq=1 ttl=63 time=31.1 ms
64 bytes from 10.198.0.10: icmp_seq=2 ttl=63 time=30.0 ms
The server starts and configures the first available TUN interface with IP address 192.168.200.1. With the directive 'topology subnet', the fake remote address is also 192.168.200.1. After that, the server listens on the UDP port 1194 for incoming connections. For security reasons, the OpenVPN process switches to user and group, nobody
. Even if a remote attacker was able to compromise the OpenVPN process, the security breach would be contained to the user nobody
instead of the user root
. When the 'user' and 'group' directives are used, it also wise to add the following as well:
persist-key persist-tun
Otherwise, OpenVPN will not be able to restart itself correctly.
Another security measure is the use of the following on the server side (and ta.key 1
on the client side):
tls-auth /etc/openvpn/cookbook/ta.key 0
This prevents the server from being overloaded by a so-called Distributed Denial of Service (DDoS) attack, as OpenVPN will just ignore those packets immediately if the HMAC is not correct.
The following directive sets up a keepalive
timer on both the client and the server side:
keepalive 10 60
Every 10 seconds, a packet is sent from the server to the client side and vice-versa, to ensure that the VPN tunnel is still up and running. If no reply is received after 60 seconds on the client side, the VPN connection is automatically restarted. On the server side, the timeout period is multiplied by 2, hence the server will restart the VPN connection if no reply is received after 120 seconds.
Finally, the following directives are very commonly used in a production setup, where the OpenVPN process continues to run in the background (daemonizes itself) after the operator logs out:
daemon log-append /var/log/openvpn.log
All output of the OpenVPN process is appended to the log file: /var/log/openvpn.log
. You can use the tail -f
command to monitor the output of the OpenVPN process.
The client connects to the server. After the initial TLS handshake, using both the client and server certificates, the client is assigned the IP address 192.168.200.2. The client configures its first available TUN interface using this information and updates its routing table so that traffic for the server-side Site B's LAN is tunneled over the VPN.
As the example files used in this recipe are reused later on , it is useful to explain a bit more about the options used.
After the connection is established, you can query the tun0
interface like this:
[client]$ /sbin/ifconfig tun0 | grep inet
Look for the following:
inet addr:192.168.200.2 P-t-P:192.168.200.2
This is caused by the directive topology subnet
, which is something new in OpenVPN 2.1. This directive tells OpenVPN to assign only a single IP address to each client. With OpenVPN 2.0, the minimum number of IP addresses per client is four (as we can see in the previous recipe).
In the previous example, we chose the UDP protocol. The configuration files in this recipe can easily be converted to use TCP protocol by changing the line:
proto udp
It should be changed to the following:
proto tcp
This should be done in both the client and server configuration files. Save these files for future use as basic-tcp-server.conf
and basic-tcp-client.conf
:
$ cd /etc/openvpn/cookbook $ sed 's/proto udp/proto tcp' basic-udp-server.conf \ > basic-tcp-server.conf $ sed 's/proto udp/proto tcp' basic-udp-client.conf \ > basic-tcp-client.conf
On the client side, the directive ns-cert-type server
is often used in combination with a server certificate that is built using:
$ build-key-server
This is done in order to prevent Man-in-the-Middle attacks. The idea is that a client will refuse to connect to a server that does not have a special server certificate. By doing this, it is no longer possible for a malicious client to pose as a server. OpenVPN 2.1 also supports the directive:
remote-cert-tls server
This also supports certificates with explicit key usage and extended key usage based on the RFC 3280 TLS rules.
In this recipe, the gateway on the server-side LAN is configured with an extra route for the VPN traffic. Sometimes, this is not possible, in which case the Linux iptables
command can be used to set up masquerading:
[root@server]# iptables -t nat -I POSTROUTING -o eth0 \ -s 192.168.200.0/24 -j MASQUERADE
This instructs the Linux kernel to rewrite all traffic that is coming from the subnet 192.168.200.0/24
(that is our OpenVPN subnet) and that is leaving the Ethernet interface eth0
. Each of these packets has its source address rewritten so that it appears as if it's coming from the OpenVPN server itself and not from the OpenVPN client. iptables
keeps track of these rewritten packets so that when a return packet is received the reverse is done and the packets are forwarded back to the OpenVPN client again. This is an easy method to enable routing to work, but there is a drawback when many clients are used, as it is no longer possible to distinguish traffic on the Site B's LAN if it is coming from the OpenVPN server itself, from client1 via the VPN tunnel, or from clientN via the VPN tunnel.