This time, I would like to describe how I setup my OpenVPN server at home. I use this server to tunnel my traffic home, when using an open Wifi network at hotels or airports, to make sure, my traffic is encrypted. I also use the tunnel. to get access to my mail server when being at work, were only our corporate mail server is allowed to reach and all others are blocked.
OpenVPN is a software which makes it possible to tunnel traffic to a server. IT looks like you have a direct connection to this server and the network in between is totally transparent. Using the software, you have two options, L3 tunneling, which will route the traffic at the OpenVPN server to the destination or L2 tunneling, which will connect the VPN clients to the local network at the OpenVPN server site. I will explain, how to use both options.
You can use the software in a server-client topology, where regular clients will connect to the server or as a point-to-point connection to interconnect different sites which each other.
The connection is always encrypted using a certificate. This makes sure, that the traffic stays private on the way from the client to the server and vice versa.
Setup OpenVPN Server
I will install OpenVPN server on
The OS itself is already installed and I will not cover this in the post.
To install OpenVPN server and openssl on Debian Jessi, simply use this command:
apt-get install openvpn openssl easy-rsa
This will install the needed packages on D
I need to change the directory to the easy-rsa directory in the OpenVPN directory:
If the directory is not there, I can copy it over:
cp -R /usr/share/easy-rsa/* easy-rsa/
I need to make sure, that I’m already in the /etc/openvpn directory.
Next step is to modify the vars file in the easy-rsa directory:
change the following lines to your needs:
export KEY_SIZE=2048 export KEY_COUNTRY="DE" export KEY_PROVINCE="NRW" export KEY_CITY="Haan" export KEY_ORG="flomain.local" export KEY_EMAIL="[email protected]" export KEY_OU="flomain.local"
To export the settings and use them during certificate creation I will execute the vars file:
To remove old certificates and configurations I will run this command:
The next step is to generate the ca. One site node here. Never send .key files using insecure communication protocols. Keep it secure and save.
I create the CA using this command:
This will create the files needed for the ca to sign certificates. The files creates are the following ones:
I will create a certificate for the OpenVPN server using this command:
This will generate the server certificate which is used by the OpenVPN server. The files are those ones:
To work properly, the OpenVPN server needs a DIFFIE-HELLMAN parameter file which will be created using this command:
This will create this file:
The last step is to create the certificates for the clients:
This needs to be done for every client and will create those files:
The following files needs to be copied over to the client:
As the certificates are in place, the next step is to create the server and client configuration files.
L3 OpenVPN Server
I will start with the easy option. The L3 tunnel is easier to implement as there is no need to change something in the infrastructure. For a small setup like mine, I will use NAT to make the VPN clients even more transparent to my home network. The l3 type of tunnel is from my point of view the default requirement and should be enough for 90% of the cases.
I will create the server config first. I will create a new file in the /etc/
/etc/openvpn# vi server_l3.conf
The content of the file looks like this:
# Port port 1194 # TCP oder UDP? proto tcp-server mode server tls-server #tun or tap device #tun is an IP tunnel, #tap an ethernet tunnel dev tun #Our Server IP server 10.0.0.0 255.255.255.0 #Paths to the certs ca /etc/openvpn/easy-rsa/keys/ca.crt cert /etc/openvpn/easy-rsa/keys/infrastructure.flomain.local.crt key /etc/openvpn/easy-rsa/keys/infrastructure.flomain.local.key #Diffie-Hellmann Parameters dh /etc/openvpn/easy-rsa/keys/dh2048.pem cipher AES-256-CBC tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 tls-version-min 1.2 remote-cert-tls client #Tests the connection with a ping like paket. (wait=120sec) keepalive 10 120 #Authenication auth SHA512 #comp comp-lzo #Sets new rights after the connection user nobody group nogroup #We need this because of user nobody/group nobody. persist-key persist-tun #Logging 0, (testing:5) verb 0
The config file is very simple. I use tcp as the transport protocol, as I have issues with upd when at the office. I need to use the created certificates for the server and set a not used IP subnet for the server IP subnet. This IP subnet will be used by the server and the client to communicate with each other. The clients will also get IP address from this subnet from the OpenVPN server.
The client file looks simple as well:
client float dev tun #tcp oder udp proto tcp-client remote infrastructure.flomain.local 1194 ca ca.crt cert client.flomain.local.crt key client.flomain.local.key cipher AES-256-CBC tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 tls-version-min 1.2 verify-x509-name infrastructure.flomain.local name remote-cert-tls server route 188.8.131.52 255.255.255.255 route 184.108.40.206 255.255.255.255 route 220.127.116.11 255.255.255.255 route 18.104.22.168 255.255.255.255 route 22.214.171.124 255.255.255.255 route 192.168.2.0 255.255.255.0 auth SHA512 nobind comp-lzo persist-key persist-tun verb 1
The client config contains the necessary certificate entries and some individual routing entries. The individual routing entries will make sure, that traffic to those destinations will be routed through the tunnel. All other traffic will use the normal default gateway configured on the client.
To use the tunnel to redirect all traffic through the tunnel the individual routing entries can be removed and this entry needs to be added:
If everything is working correctly, the client can connect to the server. Unfortunately, communication with other destinations then the server itself will fail, as the OpenVPN server is not able to route traffic. Let’s make sure, this will happen as well.
To enable routing on a Debian system use this command:
echo 1 > /proc/sys/net/ipv4/ip_forward
This will enable routing until the next system restart. To make it permanent I need to uncomment
net.ipv4.ip_forward = 1
This will make sure, that routing is enabled after the next system restart.
If the network is aware that VPN clients can be reached using the OpenVPN server, the clients are now able to use the connection. As I would like to NAT the clients to the IP of the OpenVPN server I need to tell the Debian system to do so:
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
This will instruct the system to map every packet from the 10.0.0.0/24 subnet to the IP address of the eth0 interface.
To make this permanent I need to save the iptables to a file:
iptables-save > /etc/iptables.up.rules
To load the rules on startup use a script like this:
#!/bin/sh iptables-restore < /etc/iptables.up.rules
and put it into this file:
This will make sure, that the NAT instruction is loaded after a system reboot.
L2 OpenVPN Server
Now, I will get to the tricky part. It took me more than two weeks to get this working correctly. The l2 tunnel is not needed that often. To be honest, I only tested it, because I wanted to get it working. A real requirement for the l2 tunnel would be the use of a protocol which cannot be routed, like Apple airplay or airprint.
On ESXi, the vswitch needs to run in promiscuous mode to make this work, as the vswitch did not learn mac addresses like normal switches. From my point of view, they even did not lean mac addresses at all, they simply get the information about the mac address from the ESXi server.
Enable promiscuous mode for a vm network by setting promiscuous mode to accept:
For KVM/Proxmox, it is not necessary to to something like this.
To create a
apt-get install bridge-utils
The next step, is to create the bridge. Open the following file:
Assuming, there is only one network interface in the server, the file needs to be changed to look like this:
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo br0 iface lo inet loopback # The primary network interface allow-hotplug eth0 iface eth0 inet manual allow-hotplug tap0 iface tap0 inet manual iface br0 inet static address 192.168.2.22 netmask 255.255.255.0 network 192.168.2.0 broadcast 192.168.2.255 gateway 192.168.2.1 search-domain flomain.local bridge_ports eth0 tap0 pre-up openvpn --mktun --dev tap0 post-down openvpn --rmtun --dev tap0
There are two new interfaces created. The tap0 interface will be used by the OpenVPN server. The br0 interface is the bridge, which will bring eth0 and tap0 together. The result will be, that all clients, connected to the OpenVPN server, will be placed in the same network as eth0.
As all clients will be in the same network as the server, there are two options to provide IP addresses to the clients. OpenVPN will provide IP addresses to the clients and act as the DHCP server. If choosing this option, the local DHCP server needs to be aware of this and should exclude the range, which is provided by the OpenVPN server to avoid duplicate IP addresses.
The second option is to use the local DHCP server to provide IP addresses to VPN clients as well. If choosing this option, the local DHCP server needs to be aware of VPN clients and remove the option for the gateway for VPN clients on the DHCP answers. This is very important. Ignoring this will lead to a
I have chosen the second option and my OpenVPN server config for this option looks like this:
# Port port 1194 # TCP oder UDP? proto udp mode server tls-server #tun or tap device #tun is an IP tunnel, #tap an ethernet tunnel dev tap0 #Paths to the certs ca /etc/openvpn/easy-rsa/keys/ca.crt cert /etc/openvpn/easy-rsa/keys/infrastructure.flomain.local.crt key /etc/openvpn/easy-rsa/keys/infrastructure.flomain.local.key #Diffie-Hellmann Parameters dh /etc/openvpn/easy-rsa/keys/dh2048.pem cipher AES-256-CBC tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 tls-version-min 1.2 remote-cert-tls client client-to-client #Tests the connection with a ping like paket. (wait=120sec) keepalive 10 120 #Authenication auth SHA512 push "route-gateway 192.168.2.1" push "redirect-gateway def1" #comp comp-lzo #Sets new rights after the connection user nobody group nogroup #We need this because of user nobody/group nobody. persist-key persist-tun #Logging 0, (testing:5) verb 0
The configuration looks similar the one used for the l3 tunnel. The main differences are the use of UDP instead of TCP (I use TCP for the l3 tunnel because UDP is blocked at my office), the use of the previously created tap0 interface, client to client communication is allowed, which makes sense as they are in the same network and the push commands, which tell the client to use the local gateway at the OpenVPN server site.
Why should this push method be used to provide the default gateway to the client instead of using the DHCP method? when using your local DHCP server, the routing table of the client will have a second entry for the default route, but with a much higher metric. This will cause, that this path is never used and no traffic will go through the tunnel. When using the push method for the gateway, OpenVPN will create two routes at the client. One for 0.0.0.0/126.96.36.199 and a second one for 188.8.131.52/184.108.40.206. Both will have a higher metric as the default route, but as the smallest route always win, the /220.127.116.11 netmask will make the difference. This is heavily important and it took me more than a week to figure this out.
To use the OpenVPN server for DHCP instead of the local DHCP server, insert this directive to the configuration:
server-bridge 192.168.1.10 255.255.255.0 192.168.1.100 192.168.1.110
192.168.1.10 would be the IP of the OpenVPN server in the local network and the range from 100-110 the scope for the OpenVPN clients.
The client configuration looks like this:
#this is the client client dev tap #tcp oder udp proto udp remote infrastructure.flomain.loal 1194 ca ca.crt cert arbeitslaptop.flomain.local.crt key arbeitslaptop.flomain.local.key cipher AES-256-CBC tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 tls-version-min 1.2 verify-x509-name infrastructure.flomain.local name remote-cert-tls server auth SHA512 nobind comp-lzo persist-key persist-tun verb 0
The config looks pretty strait. The same changes as for the server configuration, moving from tun to tap and from TCP to UDP.
From here, everything should work fine and even if I’m abroad, I can enjoy my local TV shows from home.
If you have any questions, regarding this post or if you would like to provide feedback, please use the comment function below.