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).