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 including the use of linear
addresses (topology subnet
).
The configuration files used in this recipe are useful building blocks for other recipes throughout this book; therefore, they are named basic-udp-server.conf
, basic-udp-client.conf
, and so on.
Install OpenVPN 2.3.9 or higher on two computers. Make sure the computers are connected over a network. Set up the client and server certificates using the previous recipe. For this recipe, the server computer was running CentOS 6 Linux and OpenVPN 2.3.9 and the client was running Fedora 20 Linux and OpenVPN 2.3.9.
We use the following network layout here:
proto udp port 1194 dev tun server 10.200.0.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/dh2048.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 # use "group nogroup" on some distros daemon log-append /var/log/openvpn.log
Then save it as basic-udp-server.conf
. Note that in some Linux distributions, the group nogroup
is used instead of nobody
.
tls-auth
secret key file from the /etc/openvpn/cookbook/keys
directory: [root@server]# cp keys/ta.key ta.key
root@server]# openvpn --config basic-udp-server.conf
[root@server]# sysctl -w net.ipv4.ip_forward=1
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 remote-cert-tls server
Save it as basic-udp-client.conf
.
tls-auth
secret key file, ta.key
, to the client machine using a secure channel, such as scp
:[root@client]# scp openvpnserver:/etc/openvpn/cookbook/keys/ta.key .
[root@client]# openvpn --config basic-udp-client.conf OpenVPN 2.3.9 x86_64-redhat-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [PKCS11] [MH] [IPv6] built on Dec 16 2015 library versions: OpenSSL 1.0.1e-fips 11 Feb 2013, LZO 2.08 Control Channel Authentication: using '/etc/openvpn/cookbook/ta.key' as a OpenVPN static key file UDPv4 link local: [undef] UDPv4 link remote: [AF_INET]openvpnserver:1194 [openvpnserver] Peer Connection Initiated with [AF_INET]openvpnserver:1194 TUN/TAP device tun0 opened do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0 /usr/sbin/ip link set dev tun0 up mtu 1500 /usr/sbin/ip addr add dev tun0 10.200.0.2/24 broadcast 10.200.0.255 Initialization Sequence Completed
gateway1
, so that all VPN traffic is sent back to the VPN server. In this recipe, we use a router that understands a Linux ip route
like syntax: [gateway1]> ip route add 10.200.0.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 the IP address 10.200.0.1
. With the directive topology subnet
, the fake remote address is also 10.200.0.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 is 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 two; 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 10.200.0.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
Then, look for the following:
inet addr:10.200.0.2 P-t-P:10.200.0.2
This is caused by the topology subnet
directive, 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 the TCP protocol by changing the following 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 as basic-tcp-server.conf
and basic-tcp-client.conf
for future use:
$ 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 remote-cert-tls server
directive is often used in combination with a server certificate that is built using the following:
$ 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. This option also supports certificates with explicit key usage and extended key usage, based on the RFC 3280 TLS rules.
Older versions of OpenVPN used the ns-cert-type server
directive. This option is still supported, but it will be deprecated in a future version of OpenVPN.
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 10.200.0.0/24 -j MASQUERADE
This instructs the Linux kernel to rewrite all traffic that is coming from the subnet 10.200.0.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. The iptables
module 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 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.
3.15.1.22