Tag Archives: VPN

OpenWrt, easy-rsa, openvpn and stunnel

Certificates are confusing. I have wanted to generate self signed certificates on OpenWrt using easy-rsa, and use them for openvpn and stunnel. Below are the relevant commands and configurations.

easy-rsa
The vpn guide for OpenWrt is quite good. A summary:

# cd /etc/easy-rsa
# vim vars                   -- edit as you like
# source ./vars
# build-ca                   -- generates ca.crt
# build-dh                   -- generates dh2048.pem
# build-key-server myserver  -- generates myserver.[crt+key+csr]
# build-key myclient         -- generates myclient.[crt+key+csr]

For stunnel purposes, you need to copy/rename your .crt file to .pem. The content is the same.

The .csr files are not needed. The clients need the ca.crt plus their .crt (or .pem) and .key files.

openvpn server

option ca '/etc/openvpn/ca.crt'
option cert '/etc/openvpn/myserver.crt'
option key '/etc/openvpn/myserver.key'
option dh '/etc/openvpn/dh2048.pem'

openvpn client

option ca '/etc/openvpn/ca.crt'
option cert '/etc/openvpn/myclient.crt'
option key '/etc/openvpn/myclient.key'

stunnel server

cert = /etc/stunnel/myserver.pem
key = /etc/stunnel/myserver.key
CAfile = /etc/stunnel/ca.crt
verify = 2

stunnel client

cert = /etc/stunnel/myclient.pem
key = /etc/stunnel/mysclient.key
CAfile = /etc/stunnel/ca.crt
verify = 2

It looks very simple now, but without a working configuration it is not so easy to find the error.

Working OpenVPN configuration

I am posting my working OpenVPN server configuration, and client configuration for Linux, Android and iOS. First a little background.

I have an OpenWRT (14.07) router running OpenVPN server. This router has a public IP address and thanks to dyn.com/dns it can be resolved using a domain name (ROUTER.PUBLIC in all configuration examples below).

My router LAN address is 192.168.8.1, the LAN network is 192.168.8.*, and the OpenVPN network is 192.168.9.* (in this range OpenVPN-clients will be given an address to their vpn/dun-device). I run OpenVPN on TCP 1143.

What I want to achieve is
1) to access local services (like ownCloud and ssh) of computers on the LAN
2) to access internet as if I were at home, when I have an internet access that is somehow restricted

The Server
Essentially, this OpenWRT OpenVPN Setup Guide is very good. Follow it. I am not going to repeat everything, just post my working configurations.

root@breidablick:/etc/config# cat openvpn 

config openvpn 'myvpn'
	option enabled '1'
	option dev 'tun'
	option proto 'tcp'
	option status '/tmp/openvpn.clients'
	option log '/tmp/openvpn.log'
	option verb '3'
	option ca '/etc/openvpn/ca.crt'
	option cert '/etc/openvpn/my-server.crt'
	option key '/etc/openvpn/my-server.key'
	option server '192.168.9.0 255.255.255.0'
	option port '1143'
	option keepalive '10 120'
	option dh '/etc/openvpn/dh2048.pem'
	option push 'redirect-gateway def1'
	option push 'dhcp-option DNS 192.168.8.1'
	option push 'route 192.168.8.0 255.255.255.0'

It is a little unclear if the last three options really work for all clients. I also have:

root@breidablick:/etc/config# cat network 
.
.
.
config interface 'vpn0'
	option ifname 'tun0'
	option proto 'none'

and

root@breidablick:/etc/config# cat firewall 
.
.
.
config zone
	option name 'vpn'
	option input 'ACCEPT'
	option forward 'ACCEPT'
	option output 'ACCEPT'
	list network 'vpn0'
.
.
.
config forwarding
	option src 'lan'
	option dest 'vpn'

config forwarding
	option src 'vpn'
	option dest 'wan'
.
.
.
# may not be needed depending on your lan policys (2 next)
config rule
	option name 'Allow-lan-vpn'
	option src 'lan'
	option dest 'vpn'
	option target ACCEPT
	option family 'ipv4'

config rule
	option name 'Allow-vpn-lan'
	option src 'vpn'
	option dest 'lan'
	option target ACCEPT
	option family 'ipv4'
.
.
.
# may not be needed depending on your wan policy
config rule
	option name 'Allow-OpenVPN-from-Internet'
	option src 'wan'
	option proto 'tcp'
	option dest_port '1143'
	option target 'ACCEPT'
	option family 'ipv4'

iOS client
You need to install OpenVPN client for iOS from the app store. The client configuration is prepared on your computer, and synced with iOS using iTunes (brilliant or braindead?). This is my working configuration:

client
dev tun
ca ca.crt
cert iphone.crt
key iphone.key
remote ROUTER.PUBLIC 1143 tcp-client
route 0.0.0.0 0.0.0.0 vpn_gateway
dhcp-option DNS 192.168.8.1
redirect-gateway def1

This route and redirect-gateway configuration makes all traffic go via VPN. Omit those lines if you want direct internet access.

Android client
For Android, you also need to install the OpenVPN client from the Store. My client is the “OpenVPN for Android” by Arne Schwabe. This client has a GUI that allows you to configure everything (but you need to get the certificate files to your Android device somehow). You can watch the entire Generated Config in the GUI and mine looks like this (omitting GUI and Android-specific stuff, and the certificates):

ifconfig-nowarn
client
verb 4
connect-retry-max 5
connect-retry 5
resolv-retry 60
dev tun
remote ROUTER.PUBLIC 1143 tcp-client
route 0.0.0.0 0.0.0.0 vpn_gateway
dhcp-option DNS 192.168.8.1
remote-cert-tls server
management-query-proxy

Linux client
I also connect linux computers occationally. The configuration is:

client
remote ROUTER.PUBLIC 1194
ca ca.crt
cert linux.crt
key linux.key
dev tun
proto tcp
nobind
auth-nocache
script-security 2
persist-key
persist-tun
user nobody
group nogroup
verb 5
# redirect-gateway local def1
log log.txt

Here the redirect-gateway is commented away, so internet traffic is not going via VPN.

Certificates
The easy-rsa package and instructions in the OpenWRT guide above are excellent. You should have different certificates for different clients. One certificate can only be used for one connection at a time.

Better configuration?
I dont say this is the optimal or best way to configure OpenVPN – but it works for me. You may prefer UDP over TCP, and may reasons for running TCP are perhaps not valid for you. You may want different encryption or data compressions options, different logging options and so on.

TP-Link WDR4900, OpenWRT and OpenVPN

My old Linksys WRT54GL has worked fine for long. I want OpenWRT and I want some VPN solution, and the last OpenWRT version that runs properly on WRT54GL is 10.03.1, which is 4 years old by now. That means old versions of all software, and possible security issues.

I gave OpenWRT Barrier Breaker RC1 a chance on my WRT54GL. I even rebuilt OpenWRT from scratch (buildroot and all) to produce a minimal image (no IPv6, among other things). It was well below 3MB big, so I had a whole MB of flash drive available, but the Wireless network just won’t run (for more than a few minutes, then the router almost halts completely). 16Mb of RAM is simply too little.

My thoughts about a new router were ultimately inspired by the announcement of the Linksys WRT1900AC. However, the WRT1900AC was supposed to be FOSS-friendly but now several months later the driver sources required by OpenWRT has still not been released. It seems Belkin has done a really ugly thing. So no thanks Linksys (owned by Belkin).

OpenWRT works on many different routers, but many of them are not very powerful (8Mb flash/32Mb RAM is common). Since I have been struggling with my WRT54GL for years I wanted to get a powerful router this time, that gives me flexibility. As soon as you want something more powerful than 8/32Mb, that is also supported by OpenWRT, you do not have so many choices. And many routers that work are hard to actually buy. To confuse things further, many routers come in different versions with different support, (Netgear WNDR3700 being perhaps the worst example).

TP Link WDR4900
I ended up with a router that is classified as Work in Progress by OpenWRT: the TP-Link WDR4900 (European version 1.3). It has 16Mb of flash and 128Mb or RAM, and a 800MHz PowerPC CPU – who could resist such amazing hardware?

As it was listed as Work in Progress I expected problems, but none so far! I have installed OpenWRT Barrier Breaker RC2 (generic, not the p1020), and I use it as most people would. Both 2.4Ghz and 5GHz WiFi works fine (although, I have read that 40Mhz band does not work, so I have not tried that). The router has 10MB available flash (compared to just 2MB, for a similar 8MB router) and 96Mb available RAM.

OpenVPN
And I have installed OpenVPN. It would be very nice with a VPN solution that works out of the box with iOS and Android, but that is PPTP (which I don’t want) or L2TP/IPSEC-solutions, which all seem very complicated and without really good support anyway. OpenVPN requires a separate App for iOS and Android, but whatever.

I followed the OpenWRT OpenVPN instructions. At first they seem complicated, but it was actually easy and successful. My only issue was that the router would not route VPN traffic to the internet. Turns out a Firewall rule was missing in the instructions (at least for me):

#/etc/config/firewall
config forwarding
	option src 'vpn'
	option dest 'wan'

And, the command “build-dh” which is supposed to take long time, took just over 60 minutes on this router.

I found that each client should have their own certificates (otherwise they get the same IP, which is bad).

Next practical question was what port and protocol should OpenVPN run? For me it is more important to always be able to connect, than to get most optimal performance. So I thought TCP/443 should be a safe choice (no one blocks that). Well, turns out there are firewalls that see the difference between HTTPS/SSL and OpenVPN/SSL and block the later. Some options could possibly be UDP/123 or UDP/53. OpenVPN over ICMP would be VERY nice.

I tried to configure a port forward on the OpenWRT router, to itself, to make OpenVPN operate on several ports. This seems to work very fine with TCP but not with UDP. Don’t really know why but I might find out some day. Alternatively I could run several instances of OpenVPN on different port/protocol combinations, but that would require more configuration (and resources) than just a port forward.

OpenWRT
I first installed BB RC1 (the full 16MB image) and later upgraded to BB RC2 (the smaller, upgrade image). Obviously, the configurations are kept, but all packages are lost – a good thing to know 😉 Well, all I need to do is exporting a list of all installed packages, before upgrade, and then run that list after upgrade. Guess I am not the first.

Also, release builds come with Luci (the web GUI) included, but trunk builds do not. I thought RC meant release candidate, implying that Luci would be included, but not so. However, very easy to find information on how to install Luci.

Benchmarking WDR4900
Benchmarks are tricky. I have a little C-program that is mostly CPU-dependent, not using floating point numbers and that outputs computation time (using clock_gettime so it should be accurate) for the problem given to it. I ran this program for problems small enough to run on my old WRT54GL, and compared the results of WRT54GL (200MHz Mips), WDR4900 (800MHz PowerPC) and an Apple PowerBook G4 (866MHz PowerPC) running Debian. In all cases I compliled with GCC and -Os (optimize for small binary). The 866MHz G4 is marginally faster than the 800MHz P1014. The PowerPCs are about 6 times faster than the old 200MHz Mips of the WRT54GL.

I have also found that the WDR4900 is about twice as fast as a Raspberry Pi for the above application.

VPN Server and Routing issues (arping)

Like many other people I have a network behind a NAT. The router providing the NAT has a real world routable IP (and a domain name using DynDNS). The router can forward ports to machines inside. So, I installed a VPN server (poptop) on a local machine. My setup:

  gateway: 192.168.0.3
  vpnserver: 192.168.0.2

I configure poptop to use the following IPs:

  #options.pptpd 
  localip 192.168.0.240
  remoteip 192.168.0.241-242

As I now connect, from the internet, to the VPN server, I get IP 192.168.0.241 (or 242), and the VPN server itself holds IP 192.168.0.240 on its ppp-device.

The VPN client can now connect to the VPN server, and the other way around. What doesnt work though is:

  1. VPN client can not connect to other local machines
  2. VPN client can especially not connect to the local gateway, and thus not access the internet via VPN

What is the problem? The other machines on the network:

  1. does not know who has IP 192.168.0.241 and can not reply to it directly
  2. does not have the VPN server (but the gateway) as default gateway

Fixing routing table
One way to fix this is to add a host entry on a local machine. On Linux that would be:

  # route add -host 192.168.0.241 gw 192.168.0.2

(route is similar but the details are different in every OS).
Well, this works, but it sucks because you have to do it on every local host. It sucks even more if you have a NAT-machine that you cannot run the route command on, because then you can anyway not access the internet via VPN anyway.

ARP-hack
I found a solution I liked better. There is a command called arpspoof. Chances are you dont have it :(. What it does is that it sends out pings to machine A, pretending it is machine B. That way, machine A will send its packages to you, instead of to machine B. Normally, that is not such a legitimate thing to do.

However, there is another program that you might have on your VPN server; arping. This program does what arpspoof does, but it doesn’t lie if you ask it to. But it doesn’t need to know it lies, does it? I wrote this little script (works on linux – requires bridge-utils – run it on the VPN server):

  #!/bin/sh
  brctl addbr tmpbr
  ifconfig tmpbr 192.168.0.241
  arping -c 1 -U -I eth0 -s 192.168.0.241 192.168.0.3
  ifconfig tmpbr down
  brctl delbr tmpbr

So we bring up a temporary virtual network interface (tmpbr). We assign it the IP we would want other computers to believe us to have. We send an arp-ping through our normal network interface (eth0), but from the IP of the VPN-client, to the default gateway. Then we bring down tmpbr.

Now, our gateway (192.168.0.3) believes the vpn server has IP 192.168.0.241 (which is actually true). And beyond my knowledge, it seems the other computers on the network learn this thing too 🙂 But they forget quickly if they dont use the information, so you need to run the above script often (like every minute).

You can run the arping command with slightly different switches and still be successful. This worked and made sense to me.

My VPN server happens to run OpenWRT. Both arping and bridge-utils are included by default. If you let the VPN-server be installed on your NAT-router everything is easier. You can also make some things work fairly well setting up a NAT-server on the VPN-server as well, making double NAT to the internet.

Windows VPN on Linux and Qemu

How to connect to a Windows VPN-server using Linux? In my case PPTP was not allowed; I was required to use L2TP and a certificate (plus domain\user and password of course). All my attempts with OpenVPN, Network Manager and Mac OS X were in vain – only Windows VPN clients seemed to work. I wanted to connect from Linux, and was successful with the following strategy:

  1. Install Windows 2000 under Qemu
  2. Configure VPN in virtual machine and share it
  3. Route VPN traffic to virtual Windows machine

My linux machine is located behind a NAT (192.168.0.2) on the 192.168.0.* network.
The network behind VPN is 10.2.*.

Windows and Qemu
I will not write a guide on how to install Windows on Qemu. But, Windows 2000 or later should work. Pick up TinyXP if you dont have a problem with it. Older version of Windows means less disk/ram usage, and you will only use it as a VPN-client anyways. On 2000/XP check out MS knowledge base article 818043.

I used real network mode in Qemu (ie a tap-device). So, I configured a bridge (br0) device, that you I connected both eth0 and tap0 to. See example below for some help. Perhaps -net user can work as well (but be aware that the Windows must have IP=192.168.0.1, see below).

Configure and Share VPN in Windows
Configuring Windows to connect to the VPN should be very easy. When you are done, right-click on your VPN connection and choose the Sharing-tab. Check “Enable Internet Connection Sharing for this connection”. Now happens something weird – the Windows machine has to have IP=192.168.0.1! You have to accept that, and hopefully your local network can be 192.168.0.* and the network you want to connect to is not 192.168.0.*.

Route VPN-traffic to Windows machine
For me, the following command on the linux machine is enough:
sudo route add -net 10.2.0.0/16 gw 192.168.0.1
Now try to ping or ssh to something on the 10.2-network. You might want to change your DNS to a DNS on the VPN.

Qemu-startup-script
I use the following script to start my Qemu machine:

  sudo route add -net 10.2.0.0/16 gw 192.168.0.1
  sudo tunctl -t tap1
  # sudo brctl addif br0 tap1
  sudo qemu -m 128 -net nic -net tap,ifname=tap1 vpn2000.qcow
  # sudo brctl delif br0 tap1
  sudo tunctl -d tap1
  sudo route del -net 10.2.0.0/16 gw 192.168.0.1

I really have no idea why I dont need to connect br0 to tap1, but it happens automatically 🙂

My working routing table looks like this:

  Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
  192.168.0.0     *               255.255.255.0   U     0      0        0 br0
  10.2.0.0        192.168.0.1     255.255.0.0     UG    0      0        0 br0
  link-local      *               255.255.0.0     U     1000   0        0 br0
  default         192.168.0.2     0.0.0.0         UG    100    0        0 br0