Archives For openvpn

A lot of people seem interested in safe browsing over untrusted wifi and using a Raspberry Pi with an OpenVPN server to accomplish that. In this blog post, I’ll continue the series and explain how to set up secure browsing on mobile devices based on iOS.

When I’m not at home I use my iPhone or iPad and connect to the internet using either 3G or public wifi. I want to configure my mobile device to setup an encrypted VPN tunnel and route all traffic through it, so I have a safe browsing experience. Fortunately, there now is an OpenVPN app available on iOS that allows you to do that! Please install this app using the App Store, and continue reading to set it all up.

Preparing and importing the certificate
I’d suggest creating a separate certificate for each device you want to connect to your OpenVPN server. Although, it is possible to reuse the certificates on multiple devices, I’d recommend not to do so. First of all you will not be able to connect at the same time. Security-wise it is also smart to use one certificate for each device: whenever you lose your device, you can easily revoke the certificate and still connect from your other devices.

cd /etc/openvpn/easy-rsa/2.0/
. ./vars
./build-key remiiphone

You will now have a private key and certificate generated for your mobile device (check the ./keys directory). To be able to work with it on a mobiel device, we convert it to pkcs12 format using this command:

openssl pkcs12 -export -in keys/remiiphone.crt -inkey keys/remiiphone.key -certfile keys/ca.crt -name remiiphone -out remiiphone.p12

The password it asks is to protect the file. Remember the password, we will need it when installing on the mobile device. The file ‘remiiphone.p12’ should be created.

Next step is to bring this file to our mobile device. I did first scp it from the Pi to my iMac, then send myself an e-mail with the .p12 file attached. Since the file is password protected, it is safe to e-mail.

When you open the e-mail on your mobile device, and click the .p12 attachment you will be asked to install the certificate. Click install and confirm installation. If your device has a passcode, you will be asked to enter it. Afterwards, you need to type the password you choose when generating the p12 file. Finally, because I use a self-signed certificate, from an untrusted CA, iOS mentions the certificate is ‘Not Trusted’. Don’t worry, it’s fine.

The screenshots below show you how it looks like:

Installing the p12 certificate

Installing the p12 certificate

Unsigned profile warning

Unsigned profile warning

Enter device code

Enter device code

Enter password

Enter password

Installed certificate

Installed certificate

Your certificate is now installed on iOS and it is ready to be used by the OpenVPN app.

Preparing and importing the OpenVPN configuration file
Next step is to provide the OpenVPN app with a configuration file. When you use the .ovpn extension, you can easily import it later on. But let’s start with setting up the configuration file.

client
dev tun
proto udp
remote pi.example.org 1194
comp-lzo
redirect-gateway
<ca>
-----BEGIN CERTIFICATE-----
...
q0c4PYC3BB7pIOA2fH7Clkb8TduDcz0kzPqStD3mVjLXx1+KVxVeGMgbj0QLbPoG
...
-----END CERTIFICATE-----
</ca>
# other options (mostly defaults)
nobind
persist-key
persist-tun
user nobody
group nogroup
resolv-retry infinite

Let me explain: This tells the OpenVPN app we’ll be using client mode and use the ‘tun’ device (the only supported in iOS). The server is using udp (choose udp or tcp) and can be found on pi.example.org using port 1194. Please adjust accordingly. Line 5 tells it to use compression, and line 6 sends all traffic through the tunnel. This is exactly what we want: this allows secure browsing.

The thing that took me some time to figure out is that you need to specify the CA certificate in the OpenVPN app. Even though it was included in the .p12 file we imported, iOS would strip it and therefore not import it. That’s why you should include it in your .ovpn file. Replace lines 8-12 with your CA certificate. It needs more lines, for sure. Just paste everything between the CA tags in the file and you’ll be fine. If you’ll get this error message, your CA is probably not right:

CORE_ERROR PolarSSL: error parsing ca certificate : X509 - The certificate format is invalid, e.g. different type expected [ERR]

Finally, I have some more settings in the file that are mostly defaults. Note: it is also possible to add your private key and certificate directly to the .ovpn file, in the same way as the CA is done above. I’d recommend not to do that because your .ovpn file is then all somebody needs to be able to connect. Since there is no password protection, e-mailing the file is insecure and dangerous!

Save the file, call it pi.ovpn or so, and e-mail this file to yourself as well. The e-mail app on iOS will allow you to import this configuration to the OpenVPN app by clicking on the file. The OpenVPN app will show your imported configuration. Confirm by tapping the  green + icon. Next step, select the certificate to use with this profile. Here you will select the certificate we imported into iOS in the previous step. As a result, we can omit the username and password fields, as we use our certificate instead.

Welcome screen

Welcome screen

Import .ovpn file

Import .ovpn file

Confirm import

Confirm import

Select certificate

Select certificate

Configuration imported

Configuration imported

Connecting..
Your OpenVPN client configuration is now imported and ready for use. Let’s test it!  All you have to do to connect, is to tap on the OFF button just below the status ‘Disconnected’. You should now be connected to your OpenVPN server. Note the VPN icon on top of the screen while you’re connected.

The best way to verify everything is working properly, is to open your mobile Safari and visit a website that displays your ip address (such as ifconfig.me). It should show your OpenVPN server’s public ip address, instead of your mobile or wifi ip address. Try disconnecting and compare the ip addresses. Cool hah?!

Connecting

Connecting

Connected

Connected!

openvpnOpenVPN is great, it allows for easy access in a secure way. But how do you keep it secure? I mean, what if someone leaves your company? Do you disable access to the OpenVPN server? You should! In this blog I’ll show you how to do it.

A feature called revoking exists in OpenVPN. Revoking a certificate means to invalidate a previously signed certificate so that it can no longer be used for authentication purposes. For this to work, we need to tell the OpenVPN server which certificates are no longer valid.

All connecting clients will then have their client certificates verified against the so-called CRL (Certificate Revoking List). Any positive match will result in the connection being dropped. Your former employees will no longer have access, even if they still have their certificates.

Creating a certificate to test with
Before we start, let’s generate a dummy certificate for testing purposes:

cd /etc/openvpn/easy-rsa/2.0/
 . ./vars
./build-key unwanted-client-name

Verify you can connect to the OpenVPN server using this certificate. Refer to my earlier post for more info. Now that this works, I’ll show you how to revoke this certificate so you will no longer be able to connect.

Revoking a certificate
To revoke a certificate, we’ll use the ‘easy-rsa’ toolset.

cd /etc/openvpn/easy-rsa/2.0

If it’s not there, look at the OpenVPN examples and copy it:

cp -R /usr/share/doc/openvpn/examples/easy-rsa /etc/openvpn
cd /etc/openvpn/easy-rsa/2.0

Run this command to revoke the certificate called ‘unwanted-client-name’:

./revoke-all unwanted-client-name

You should see output similar to this:

Using configuration from /etc/openvpn/easy-rsa/2.0/openssl-1.0.0.cnf
Revoking Certificate 03.
Data Base Updated
Using configuration from /etc/openvpn/easy-rsa/2.0/openssl-1.0.0.cnf
unwanted-client-name.crt: C = NL, ST = ZH, L = City, O = Name, OU = pi.example.org, CN = unwanted-client-name, name = unwanted-client-name], emailAddress = openvpn@example.org
error 23 at 0 depth lookup:certificate revoked

Note the “error 23” in the last line. That is what you want to see, as it indicates that a certificate verification of the revoked certificate failed.

The index.txt file on keys directory will be updated. You’ll see an ‘R’ (for Revoked) on the first column from the left for your user when you run this:

cat keys/index.txt

You can also examine the CRL to see what’s in there:

openssl crl -in keys/crl.pem -text

Now copy the crl.pem file to the OpenVPN config directory:

cp keys/crl.pem /etc/openvpn/

Whenever you revoke a certificate, you’ve to copy it to the OpenVPN server.
Note: The CRL file is not secret, and should be made world-readable so that the OpenVPN daemon can read it after root privileges have been dropped.

Enable revoking support
Before it works, we need to setup the OpenVPN server to add support for revoking certificates. You’ve to do this only once.

Add the folowing line to the OpenVPN server config:

vim /etc/openvpn/server.conf
crl-verify /etc/openvpn/crl.pem

Reload the OpenVPN server to activate the revoke setting:

/etc/init.d/openvpn reload

Testing the revoked certificate
The final test: try to login again using the ‘unwanted-client-name’ certificate. It will not work anymore!

By revoking users, you disallow access to your OpenVPN server for users that previously had access. This should be done as soon as an user no longer needs access, as it is an important security feature.

The Raspberry Pi can easily be setup as an OpenVPN server. One common feature is to access servers or services on the remote network. Another use case is to provide a secure connection when you’re not at home.

You can do this by sending all traffic over the VPN connection, instead of only traffic for the remote servers. The idea is to connect your laptop to your OpenVPN server (this is encrypted by default) and access the internet from there. Whatever you send over the wifi connection, is encrypted by the VPN and thus safe. In the comments on the previous post there was someone trying to set this up. To help him solve the issue, I tested this myself, and decided to write a post showing how to do it because I really like the idea.

This is how it looks like: you’re on a untrusted network (red) and create a safe VPN connection (green) and all traffic will flow over the green network, to the also trusted home network (lighter green). People on the red network now cannot see the sites you visit.

OpenVPN secure wifi browsing

Here’s how to set it up:

  1. Allow the OpenVPN server to route ip traffic
  2. Tell the default gw where to send traffic for OpenVPN clients
  3. Send DNS servers to the VPN Clients
  4. Configure the OpenVPN Client
  5. Test your setup

Allow the OpenVPN server to route ip traffic
First of all, you need to allow the OpenVPN server to route packets.

sudo vim /etc/sysctl.conf

Add this line, or alter it if it already exists:

net.ipv4.ip_forward = 1

Then activate the change:

sudo sysctl -p

The change is now activated, and persistent.

Tell the default gw where to send traffic for OpenVPN clients
Another important step is to tell the default gateway in the home network (lighter green) where to send traffic for theOpenVPN clients. If you omit this step, this traffic gets lost. More info in this post. Short story: add this static route to your default gateway. If it’s Linux, you’d run:

sudo route add -net 10.8.0.0/24 gw 10.5.5.5

Assuming 10.5.5.5 is the ip address of the OpenVPN server. When your router is not Linux, check the manual on howto add a static route.

Send DNS servers to the VPN clients
Most ISP’s restrict the usage of their DNS servers to their own network. When you connect to Wifi, you probably receive some DNS servers via DHCP. When you connect to VPN and then send all traffic through the VPN, you are effectively using the network (and internet connection) of your VPN server and not the local network. The DNS-servers you received via DHCP might not work because you access them from another network. To solve this, configure the OpenVPN server to push public DNS servers to use. Alternatively you can also push some local DNS servers or the DNS servers of your ISP.

sudo vim /etc/openvpn/server.conf

Add or edit these lines:

push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

These are Google’s public DNS servers. Just enter some DNS servers that work on the network of your OpenVPN server and that you are allowed to use.

Configure the OpenVPN client
I’m using Viscosity and all I have to do is enable a setting to send all traffic over the VPN connection.

viscosity_enable_all_traffic_over_vpn

Alternative way: It’s also possible to configure the ‘Send all traffic over VPN connection’ on the server-side instead of the client. Both has pros and cons, of course. To set it server-side set this option in the server config:

push "redirect-gateway def1"

Test your setup
The final step: test your setup! Make sure you’re connected through some other network than the one the OpenVPN server is in. Use some public Wifi service of connect over 3G. My iPhone can share its 3G connection and start a Wifi hotspot. My MacBook connects via Wifi, then does the OpenVPN connection to the Pi. The expected behavior is then to see the public ip address of the OpenVPN server’s internet connection, instead of the 3G ip address. Use a website like whatismyip.com to test this. Do this before connecting the VPN, and after. It should be different.

Enjoy your secure browsing experience!

OpenVPN is a very powerful tool to connect to a remote network in a secure and easy way. But while it’s quite easy to set it up (see my post about OpenVPN on Raspberry Pi), getting all the pieces together takes some more network understanding and configuration. I created an image to show what’s going on when a OpenVPN client connects to the server.

OpenVPN networking

The grey network is the local network you’re connecting to, the green network is created by OpenVPN. After a successful connection, the OpenVPN server can ‘push’ a route to the OpenVPN client to make it aware of the grey network that is available through the OpenVPN connection. In this case you’d add this setting to the OpenVPN server:

push "route 10.5.5.0 255.255.255.0"

Now that the OpenVPN client knows how to find the Linux server on the grey network, it should be working, right? Nope. The Linux server does not know about the green network. So, when a OpenVPN client connects with a 10.8.0.x ip-address, this server does not know where to send the response to. When this happens, the Linux server sends its traffic to the default gateway of the local network: the router of the grey network.

But unfortunately, the router does not know about the green network neither. Since 10.8.0.x is a non-routable address (RFC 1918), it drops the packets because it has no way of knowing where to find this private network. To the OpenVPN client, this may look like there’s something wrong with the VPN connection, because even a simple ping will not work and times out. In reality, this is a routing problem.

The solution? Make the Linux server or at least the router aware of the green network, and tell them where to send traffic to this network. This is done by adding a route like this:

route add -net 10.8.0.0/24 gw 10.5.5.5

Assuming the local network ip-address of the OpenVPN server is 10.5.5.5.

This way the hosts in the grey network know about the green network and send their traffic to the OpenVPN server. Of course the OpenVPN server knows how to reach the OpenVPN client and all is working!

You can extend this further and add routes to the network of the VPN client and make hosts on both networks communicate to each other. This is useful for example to connect a branch-office to the corporate network. I’ll write about this in more detail some other time.

Hopefully this post brings some insight in what goes on when using networks and VPN connections.

The Raspberry Pi is a $35 credit-card sized computer, with an ARM-based CPU. It uses very little power (only 3 Watt), so it’s ideal for a server that’s always-on. I was thinking what’d be a nice task for my Raspberry Pi and came up with an OpenVPN server. This enables me to connect to my home from anywhere, for example to access some files or to access the internet from there.

Before we start, Let’s have a look what’s on board the Raspberry Pi so you’ve an idea what we talk about:

RaspiModelB

Here’s mine in action:

RaspberryPi

Now, let’s see how we can turn it into a OpenVPN server. Actually this is very easy due to the fact that the Raspberry Pi is running (a modified) Debian Weezy called Raspbian. Since it’s Debian, you can use apt-get to install software:

apt-get install openvpn

After the install finishes, you need to generate keys for the server and the client(s). OpenVPN ships with the ‘easy-rsa’-tool. It’s easiest to copy the example folder and work from there.

cp -R /usr/share/doc/openvpn/examples/easy-rsa /etc/openvpn
cd /etc/openvpn/easy-rsa/2.0

The ‘easy-rsa’-tool has a file called ‘vars’ that you can edit to set some defaults. That will save you time later on but it’s not required to do so.

Load the vars like this (note the two dots):

. ./vars

Then we need to generate keys:

./clean-all
./build-ca
./build-key-server server
./build-key client-name
./build-dh

The first line makes sure we start from scratch. The second generates a key for the Certificate Authority. The key for the server itself is generated on the third line. Repeat the forth line for each client that needs to connect. Finally, we need the Diffie Hellman key as well, which is generated on the fifth line. Make sure you use a 2048 bit key, as suggested in the comments.

We need to copy the keys to the OpenVPN folder.

cd /etc/openvpn/easy-rsa/2.0/keys
cp ca.crt ca.key dh2048.pem server.crt server.key /etc/openvpn

Last step is to configure the server. You can copy the example config and make sure it points to the certs you just created.

cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn
gunzip /etc/openvpn/server.conf.gz
vim /etc/openvpn/server.conf

When you’re done, start OpenVPN like this:

/etc/init.d/openvpn start

Response looks like:

[ ok ] Starting virtual private network daemon: server.

Verify it by running:

ifconfig tun0

You’ll see:

tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 
 inet addr:10.8.0.1 P-t-P:10.8.0.2 Mask:255.255.255.255
 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
 RX packets:49 errors:0 dropped:0 overruns:0 frame:0
 TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:100 
 RX bytes:3772 (3.6 KiB) TX bytes:1212 (1.1 KiB)

Now you should be able to connect to the OpenVPN server with a client. I’m using Viscosity on Mac OSX, but there’re many clients available on almost any platform (Windows, Mac OSX, Linux). You need the client.crt, client.key and ca.crt files plus the ip-address of your Raspberry Pi.

viscosity-vpn-config

Connecting should now work without trouble. Have a look at ‘/var/log/syslog’ to access the logfiles. You’d be able to see which client connects:

Jan 5 22:07:56 raspberrypi ovpn-server[14459]: 1.2.3.4:64805 [client-name] Peer Connection Initiated with [AF_INET]1.2.3.4:64805

Now that all is working, time for a last tip: when you want to access the network behind the Raspberry Pi through your OpenVPN connection, configure OpenVPN to push the right route to the clients. Edit the OpenVPN server config, and add a parameter like this:

push "route 10.1.7.0 255.255.255.0"

Be sure to enter the network- and netmask address that match your network setup. The route is automatically added on connect, and removed on disconnect.

Finally, enable routing on the Rasperry Pi:

echo 1 > /proc/sys/net/ipv4/conf/all/forwarding

Have fun with it, you can do a lot of great things with this little machine!

Update: Also see these follow-up posts that contain more detailed info on some interesting use cases and help you set it up:

HOWTO connect to hosts on a remote network using OpenVPN and some routing

Secure browsing via untrusted wifi networks using OpenVPN and the Raspberry Pi

Last week I wrote a small blog about OpenVPN on OSX Mountain Lion using Tunnelblick. I managed to get things to work using the latest Tunnelblick beta. But after a week working with it, I’m not too happy how it works right now. The two issues I have are:

1. DNS servers do not always get set properly, it feels unstable to me. I’ve seen /etc/resolv.conf with the right content, but still the old DNS servers were used by Mountain Lion. This is annoying: while connected to the vpn, hosts behind it do not resolve because the DNS server advertised by the OpenVPN server is not being used. This happened a few times last week, although most of the time it works ok. What goes wrong more often is the opposite: when disconnecting the connection, the OpenVPN advertised DNS server is still being used; but since we’re disconnected, it doesn’t resolve anymore and so nothing works. I’ve then to manually restore the right DNS servers. No fun, but I accepted it for now. I thought there’d be an update soon enough that’d solve this.

2. Problem two is more annoying: the connection is not stable, it’s slow and when working in a shell it is annoying to wait for the cursor to move. It frustrates me. I’d already blamed the guys in the office for heavy downloading only to discover it was Tunnelblick that was the problem. Sorry guys 😉 Connections to public hosts are fine by the way; I wasn’t really able to pinpoint this issue. It kept me from working effectively. If somebody knows what to do to get this working properly, let me know!

So I thought it’d be wise to look for an alternative, and I came across Viscosity. I just wanted to compare and see if it has the same issues. Don’t get me wrong: I always prefer open source software, but it does have to work. Tunnelblick and Mountain Lion clearly doesn’t work for me. Viscosity is $9 for a license, that sounds ok to me.

Downloading and installing is easy, like any other OSX app you open the dmg and drag the application to the application folder. That’s it. What surprised me was that it has an import feature that imports from Tunnelblick. One click, that’s all..

Now that’s cool. From the upper menu, you can now connect. I just works, a few seconds later I’m connected and.. DNS is handled properly. I tried connecting, disconnecting and all but can’t find any problem. It uses the OpenVPN specified DNS servers while connected, and the DHCP specified DNS servers while disconnected. Just like when I was running Tunnelblick on Lion. Also, I haven’t seen the slow connection issue. It’s a bit early to tell if that is gone for good. Since I have 30 days to try Viscosity, I’ll soon enough know 🙂

For me this is a fast en good solution. I hope Tunnelblick is able to sort out what goes wrong with Mountain Lion. Otherwise Viscosity probably has a lot of new users to welcome in the coming months. Kudos to the Sparklabs team!

Update: I did go back to Tunnelblick a few times but had no lock and didn’t want to spend more time on it. Then I bought Viscosity that just works and has been stable from the start.

I just upgraded to OSX Mountain Lion and had some trouble this morning getting my OpenVPN connection (using Tunnelblick) to work. It would connect, but the DNS resolving was unstable. I managed to get it to work on the latest stable by changing the DNS-server setting to ‘set nameserver 3.0b10’ but then internet traffic would not work. The best solution for me at the moment is to upgrade to Beta release 3.3beta16 3.3beta18.

After upgrading, everything works as expected!

More info:

  1. Mountain Lion DNS issues with Tunnelblick
  2. Discussion the issue

Update: see this blog I wrote as well (experience after one week)

Update 2: TunnelBlick 3.3 beta 18 has just been released and the release notes state it has fixed more Mountain Lion bugs.