Since the recent import of OpenSSH 4.4p1 into FreeBSD RELENG_6 I have been meaning to test the (in OpenSSH 4.3p1) new VPN over tun(4) feature. As I was unable to find any FreeBSD specific instructions – and as the instructions supplied with OpenSSH are specific to OpenBSD – I decided to document my setup here.
The examples below assign the IP address 10.0.3.1 to the server side VPN endpoint while the client side VPN endpoint is assigned the IP address 10.0.3.2. Don’t forget to update the firewall configuration on both ends to allow traffic to/from these IPs.
On the server side you need to add the following lines to /etc/ssh/sshd_config:
PermitRootLogin yes PermitTunnel yes
You also need to add the following line to /root/.ssh/authorized_keys (replacing ‘ssh-dss …’ with the actual SSH public key, of course):
tunnel="0",command="/sbin/ifconfig tun0 10.0.3.1/30 10.0.3.2" ssh-dss ...
You can append ‘; /bin/echo VPN established’ or similar to the above command to receive visual feedback on the client once the VPN connection is established.
On the client you need to add the following entry to /root/.ssh/config (Replacing ‘vpn.example.com’ with the hostname of the server side VPN endpoint):
Host vpn HostName vpn.example.com User root IdentityFile ~/.ssh/id_dsa_vpn Tunnel yes TunnelDevice 0:any PermitLocalCommand yes LocalCommand /bin/echo > /dev/tun0; /sbin/ifconfig tun0 10.0.3.2/30 10.0.3.1
I recommend using a dedicated SSH key (here ~/.ssh/id_dsa_vpn) for authenticating the tunnel, but this is of course optional. The ‘/bin/echo > /dev/tun0’ command is needed to avoid a race condition where ifconfig(8) is called before the tun0 interface is created.
Once the above configuration has been made you can establish the VPN connection simply by executing:
# ssh vpn
Hit Ctrl+C to close the VPN connection again. Please note that the tun0 interface is not destroyed upon closing the tunnel. The interface is merely brought down and the routing table entry is deleted. See the tun(4) manual page for more information.
Update: Following this commit to the FreeBSD src tree, the tun0 interface is correctly destroyed upon closing the tunnel.
If you wish to route more nets through the VPN connection it is as simple as appending an ‘/sbin/route add -net 10.0.0.0/16 10.0.3.1’ or similar command to the authorized_keys entry.
To increase security you can add a dedicated user account with privileges to create and configure the tun0 interface (e.g. via security/sudo) and instead use that account for establishing the VPN connection. This is left as an exercise for the reader.