OpenVPN on Kamikaze

Ok, here is a slightly new take on using OpenVPN on OpenWRT! I say new because all of the tutorials I’ve seen so far were not adapted to the UCI configuration framework currently used on OpenWRT.

First, the obligatory background information: I am running a self-compiled OpenWRT at revision 15252 on an Asus WL-500gP v1; because of the v1’s Broadcom card, I temporarily stopped tracking SVN as recent builds won’t work, pending a driver change, hence the ancient revision. Then, I wanted to use the nonstandard port 53 for the VPN since it has a better chance to be unfiltered at most locations than any other port: I’ll explain the acrobatics involved in keeping OpenVPN and DnsMasq off each other’s throat later on.

Configuration

UCI stores settings for OpenVPN in /etc/config/openvpn: this file has multiple stanzas, one for each VPN configuration; there are two sample configs (server and client) and a hook for adding a customized external config file, which we won’t use. Instead we’ll add a new stanza, right under the “Package” keyword:

config openvpn <newvpnname>
option enable 1
option ca /etc/openvpn/ca.crt
option cert /etc/openvpn/server.crt
option comp_lzo 1
option dev tun
option dh /etc/openvpn/dh1024.pem
option ifconfig_pool_persist /tmp/ipp.txt
option keepalive "10 120"
option key /etc/openvpn/server.key
option local a.b.c.d
option max_clients 5
option mtu_test 1
option persist_key 1
option persist_tun 1
option port 53
option proto udp
list push "dhcp-option DNS 10.13.37.1"
option script_security 2
option server "10.13.37.0 255.255.255.0"
option status /tmp/openvpn-status.log
option topology subnet
option up /etc/openvpn/vpn-fw-helper.sh
option user nobody
option verb 3

Looks simple enough, right? Let’s take a closer look anyway:

  • the <newvpnname> parameter is used by UCI to identify different subsections of the config and by syslog to label messages: pick a reasonable name, just take care not to use an existing name like sample_server and so on!
  • the enable option is the master switch for our new configuration stanza: by toggling it, we can enable&disable our section using UCI’s commandline tool.
  • there is no default path in UCI so all key and cert files must use a full pathname
  • local: ip address for the vpn server, normally not needed when the wan port has a dynamic addresss; it is required in this setup because of the port choice

Port 53 gotchas

Reading about a vpn running on port 53 should send a shiver down your spine, since you remember another slightly more common service already using that same port: the DNS!

Dnsmasq

No worries, we’ll just tell dnsmasq to bind the lan interface and openvpn to bind the wan side. Easy? Not quite: for starters, having dnsmasq bind only br-lan means not being able to provide a dns server on the vpn link. No, you can’t just run another instance of dnsmasq, because it will insist in binding localhost in addition to the vpn interface and localhost:53 is already taken by… right, dnsmasq for the br-lan segment. Sounds like a game of Mikado, heh?

Now, edit /etc/config/dhcp either directly or through the niceĀ  LUCI web interface and add:

option 'interfaces' 'br-lan'

or whatever the name of your lan segment is, then reload dnsmasq.

One last step: we need to restart dnsmasq when the vpn is started, to add its interface to the commandline. This is achieved through the “up” hook and a helper script, that uses the uci_set_state function so that the change is not retained across reboots.

OpenVPN

The “port” keyword in the config forces us to enter a local IP address for the OpenVPN server but this information will be different each time the WAN connection is started. Solution is to disable autostarting of the vpn and use hotplug to dynamically reconfigure and restart openvpn when the WAN connection is estabilished. 30-openvpn should be placed under /etc/hotplug.d/iface and will add the “local” keyword together with the address to the configuration. It is a rather crude hack, as it does not yet check whether the old config had the keyword or not but it works for me.

Final notes

I have tested this configuration with the current clients on Kubuntu 9.04, N810 and Windows XP. Of course, the connecting clients will need some kind of dynamic dns service to locate the server. It works but there is clearly room for improvement: for example, the helper script will not be run again if the firewall configuration is reloaded so forwarding will be lost. I have yet to figure out the cleanest way to configure the firewall so that no more rules are added than strictly necessary.

EDIT: of course, after getting a N900 and testing the vpn over the UMTS connection, I had to change the port from 53 to 443…. serves me right! :-)

One Response to “OpenVPN on Kamikaze”

  1. andrew says:

    openvpn on udp/53. you evil genius.

Leave a Reply

You must be logged in to post a comment.