08 August 2010

Ubuntu VPN Client Setup

Not a Java topic this time: Setting up an IPSec VPN client on my Linux box was a complete nightmare. The final solution is rather easy, but I wasted hours and hours trying different clients with different configurations which simply did not work...


This is the environment:
  • Linux client machine running Kubuntu 10.04.
  • Network interface eth0 on client configured via DHCP from a Netgear Router.
  • The router acts as DNS server.
  • The home network is 192.168.0.0/24.
  • The company network has a FortiGate firewall with an IPSec VPN.
  • The IPSec tunnel uses a pre-shared key and XAUTH username/password authentication.
  • The company network is 172.16.0.0/16, VPN clients get a virtual IP adress from 172.19.0.0/24 via DHCP-over-IPSec.
The problem:
  • There is no official Linux VPN client for FortiGate. (This is rather ironic, given that Fortinet products include GPLed Linux code, which became public after a GPL violation injunction in 2005.)
  • Ubuntu has just too many too buggy VPN clients and too little readable documentation on VPN setup. (I tried KNetworkManager, kvpnc, ike and openswan, mostly getting only error messages I could not make sense of. ike did work ocasionally, but most of the time, the incoming packets from the tunnel would not reach my client port.)
My solution:
  • strongswan for the IPSec tunnel
  • dnsmasq for merging the public and private DNS zones
  • eth0 now uses manual configuration instead of DHCP
Now for the details: The XAUTH credentials and the pre-shared key are stored in /etc/ipsec.secrets:

: XAUTH myusername "MyPassword"
: PSK "MyPreSharedKey"

The general and connection specific settings for IPSec are in /etc/ipsec.conf:

config setup
     nat_traversal=yes
                                                             
conn office
     left=%defaultroute
     leftsourceip=172.19.0.99
     right=firewall.example.com
     rightsubnet=172.16.0.0/16
     auto=add
     authby=xauthpsk


The only flaw is the explicit virtual IP address: I tried using leftsourceip=%config to let the client use an address assigned by the server, but this did not work as FortiGate does not support the ModeCfg protocol (at least not in the firmware version we are currently using), and I could not find out how to set up DHCP-over-IPSec with strongswan, so I ended up using an explicit address not part of the DHCP pool.

After editing these files and starting the tunnel via

ipsec restart
ipsec up office

I could successfully ping addresses from the office network.

In contrast both to the Windows FortiClient and the Shrew VPN Client (ikea), strongswan does not require a virtual network device and does not change the routing table. You can see the IPSec tunnel and the corresponding policies using the commands

ip xfrm state
ip xfrm policy

The log output from the strongswan IKEv1 daemon named pluto can be found in /etc/auth.log.

Now for DNS: Of course I don't want all my DNS requests for things like schweinebildchen.com to hit the office DNS server while the tunnel is up, so I'm using dnsmasq as a simple DNS proxy which redirects all DNS requests from my local machine either to my home router or to the office DNS server via the tunnel, depending on the domain.

The dnsmasq configuration in /etc/dnsmasq.conf is as simple as this:

server=/example.com/172.16.0.2
server=192.168.0.1


Finally, I changed the configuration of my network interface eth0 from auto to manual, using the IP address 192.168.0.5 and set this as nameserver in /etc/resolv.conf.

This means that all DNS requests are first handled by dnsmasq on my local machine, requests for example.com get forwarded to the office DNS server (via the IPSec tunnel), and everything else gets routed to my Netgear router (and from there to my ISP).