Pelicanux

Just A Few Random Words

OpenVPN

How I installed OpenVPN on both my laptop and my server

Ok, to be fair, I followed most parts described here. Some parts may be similar, or even copy/paste-like, but I also tried to explain each point where I spend time to understand, to make it clearer.

First steps

Of course, one can recompile from sources, but I just run

1
aptitude install openvpn

Here is how to check immediately if the connection is correctly set:

1
2
3
4
5
# On server side
openvpn --remote $Client_IP --dev tun1 --ifconfig $Server_Internal_IP $Client_Internal_IP

# On client side
openvpn --remote $Server_IP --dev tun1 --ifconfig $Client_Internal_IP $Server_Internal_IP

Just make sure $Client_IP and $Server_IP are IP addresses on the Internet and Internal ones are private IP addresses not used in any of both networks (10.9.8.1/10.9.8.2 may be a good choice).

OpenVPN will complain on both sides that the connection is not encrypted, and all traffic is transmetted clear-text, this is just to check if there is any firewall around blocking our tunnel.

If you can ping from each part your partener:

1
2
3
4
5
# On server side
ping $Client_Internal_IP

# On client side
ping $Server_Internal_IP

then everything goes just fine. You may then go forward. Otherwise, I would suggest having a look at your firewall rules, either locally (on your box, or your client) or between (enterprise firewall for instance; we will come to this point later).

OpenVPN with static keys

OpenVPN provides a command to generate static keys; and they are directly created with appropriate rights. I usually prefer creating a folder containing them. The key needs to be copied on the same folder on the other side (pre-shared keys).

1
2
umask 077 && mkdir keys && umask 0022 && cd keys
openvpn --genkey --secret static.key

Here is the configuration files:

1
2
3
4
5
6
7
8
9
10
# On server side; /etc/openvpn/tun0.conf
dev tun0
ifconfig 10.9.8.1 10.9.8.2
secret /etc/openvpn/keys/static.key

# On client side; same file
remote $Server_IP
dev tun0
ifconfig 10.9.8.2 10.9.8.1
secret /etc/openvpn/keys/static.key

Restart OpenVPN on both side and check again if from each side you can ping the other.

OpenVPN with certificates

Ok, pre-shared keys are nice, but it usually goes better with a PKI and a Certificate Authority (CA) giving guarantee on the identity of both the client and the server.

About best practices, it is better to allocate a third computer, without any network connexion if possible, to play the role of CA. It is always better to create certificates on this computer, even if most of tutorials and documentations make the certificates creation on OpenVPN server itself. Just make sure openvpn package is installed on this computer and create the different certificates:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mkdir /etc/openvpn/easy-rsa
cp -R /usr/share/doc/openvpn/examples/easy-rsa/2.0/* easy-rsa
cd easy-rsa
# Now, edit vars file to fill your own enterprise data
umask 077 && mkdir keys && umask 0022
cd keys
touch index.txt
echo 01 > serial
. ../vars # source the values you set in vars file
./build-ca # This will create both your CA key and certificate.
./build-dh

# Now, you can create keys/certificates for your client and your server
./build-key philippe
./build-key vpn.pelicanux.net

# Now, copy (USB Stick):
# ca.crt, philippe.crt, and philippe.key on your client
# ca.crt, vpn.pelicanux.net.crt, and vpn.pelicanux.net.key on your server

Now, create a configuration file for your server:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
port 1194
proto udp
dev tun

ca      /etc/openvpn/easy-rsa/keys/ca.crt
cert    /etc/openvpn/easy-rsa/keys/vpn.pelicanux.net.crt
key     /etc/openvpn/easy-rsa/keys/vpn.pelicanux.net.key
dh      /etc/openvpn/easy-rsa/keys/dh1024.pem

server $Internal_Subnets 255.255.255.0
ifconfig-pool-persist ipp.txt

keepalive 10 120

comp-lzo
persist-key
persist-tun

status log/openvpn.log

verb 3
client-to-client

$Internal_Subnets is the network you have chosen to bring up the OpenVPN tunnel (here, we choose 10.9.8.0/24). Create log directory and openvpn.log file.

On client side:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
client
dev tun
port 1194
proto udp

remote $Server_IP 1194
nobind

ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/philippe.crt
key /etc/openvpn/easy-rsa/keys/philippe.key

comp-lzo
persist-key
persist-tun

verb 3

Don’t forget to rename your tun0.conf file to something like tun0.conf.DISABLED, as every *.conf files will be taken into account by the OpenVPN daemon. Restart both client and server, first the server, and then the client, and check the connection is possible (PING both side, as usual).

can’t access LAN behind OpenVPN

At this point, you can ping the next hop, but not any further. Lots of people got stuck here. No lan access, Can’t ping/access servers on local network, LAN behind router not accessible with openvpn, and so on, and so on.

Well, first of all, Server needs to route packets when received.

1
2
3
4
# for immediate/non-permanent usage
sysctl -w 'net.ipv4.ip_forward = 1'
# For permanent usage, sysctl -P to load it immediately
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf && sysctl -P

Then, client must setup its default gateway to the $Server_Internal_IP. But not for joining the $IP_Server itself! The OpenVPN connects through the Internet, and you need to access your OpenVPN server with the route you usually use to go to the Internet!

1
2
3
4
5
6
# VPN server is to be reached as a normal host in the Internet,
# so I keep my usual default gateway for this host.
route add $Server_IP via 192.168.1.1 dev eth0
# But the trafic goes into the tunnel.
# 10.9.8.2 is the $Client_Internal_IP
route change default via 10.9.8.2 dev tun0 proto static

Now, I appear on the VPN server as 10.9.8.2. As a classic internal host with its private IP address. Hence, the gateway (here, the OpenVPN server itself, but not necessary) needs to NAT or Route my IP address. If my OpenVPN server is at the same time my new gateway:

1
iptables -t nat -A POSTROUTING -s 10.9.8.0/24 -o eth0 -j MASQUERADE

Otherwise, the trafic will go through the OpenVPN server’s gateway (and may need to be NATed elsewhere).

Just a few last things

I hope this cover the most. Here is the script I used with certificate to check out the server configuration with certificates:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

openvpn \
  --dev tun1 \
  --ifconfig 10.9.8.1 10.9.8.2 \
  --tls-server \
  --dh /etc/openvpn/easy-rsa/keys/dh1024.pem \
  --ca /etc/openvpn/easy-rsa/keys/ca.crt \
  --cert /etc/openvpn/easy-rsa/keys/vpn.pelicanux.net.crt \
  --key /etc/openvpn/easy-rsa/keys/vpn.pelicanux.net.key \
  --reneg-sec 60 \
  --verb 5

And on client side:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

openvpn \
  --remote $Server_IP \
  --dev tun1 \
  --ifconfig 10.9.8.2 10.9.8.1 \
  --tls-client \
  --ca /etc/openvpn/easy-rsa/keys/ca.crt \
  --cert /etc/openvpn/easy-rsa/keys/philippe.crt \
  --key /etc/openvpn/easy-rsa/keys/philippe.key \
  --reneg-sec 80 \
  --verb 5

About enterprise firewall troubles

If neither your own local firewall, nor your server firewall is blocking the trafic, it may be because of your enterprise firewall. Then, we just need to find a weakness to the usual firewall strategy to still go through. The idea here is similar to those developped when dealing with SSH-Tunneling. Keep in mind this lower the global security of your enterprise, and as a sysadmin, I will enjoy fucking you up if I find it through.

The idea is simply to use a port none can’t allow blocking. Such as 80/TCP HTTP (but this one gets easely proxyfied) or 443/TCP HTTPS or 53/UDP DNS. The last two will perfectly work and most of time bypass enterprise firewalls.

  • 443/HTTPS force you to use a TCP connection. This is not too bad (usually, pro-UDP says that TCP in TCP would result in performance issue, but this is not so right, YMMV).
  • Both need OpenVPN server listens on ports other services usually listen at: If you have a HTTP[S] server, well, you may need to shut it off.

To avoid this, a solution is to fix the OpenVPN source port and create on server side a firewall rule to redirect packets with this chosen port to the OpenVPN service, letting every other connection reaching the target server. This is clearly not optimal, as unlucky people trying to reach you site would end up with your OpenVPN server, without knowing what to do with this, (or glade to discover this unsuspected service). But anyway, these two iptables rules will do the trick:

1
2
iptables -t nat -A PREROUTING -p tcp --sport 1194  --dport 433  -d 5.39.82.22 -i eth0 -j REDIRECT --to-port 443
iptables -t nat -A PREROUTING -p tcp --dport 443 ! --sport 1194 -d 5.39.82.22 -i eth0 -j DNAT --to $internal_HTTPS_IP:433
  • I have thought, this would be possible to use the UDP:53 port as well; thinking of many wifi which redirect you to an authentication webpage. Well, if the DNS port is not firewalled (try contacting directly your DNS server with a command such as dig pelicanux.net @5.39.82.22), then you can also use OpenVPN to get Internet for free. In this case, you don’t go through the wifi DNS, and this is possible only if every DNS ports are open to the Internet. But most of time, the DNS port is redirected to this DNS resolver, which will need a DNS query it can understand (respecting the standards, especially RFC1035) in order to process it. (see this superuser post) or similar.