OpenSSH is a FREE version of the SSH connectivity tools
developed by the OpenBSD project. It certainly needs no introduction as it has now grown into the de facto standard for secure console access over the Internet, widely supplanting the infamous "r" commands.
Beginning with version 4.3, OpenSSH also provides secure VPN tunneling capabilities at both layer 2 and layer 3 of the OSI model, by using the tun(4) pseudo-device to encapsulate network traffic within SSH packets.
Of the VPN solutions we've seen so far, OpenSSH-based VPNs are by far the simplest to use and the fastest to implement; however, they also imply a considerable overhead. As a consequence, the documentation warns that OpenSSH VPNs may be more suited to temporary setups, such as for wireless VPNs
, and recommends the use of IPsec for more permanent VPNs.
We will configure the same VPN topology as in the previous chapters; the VPN1 machine will act as the OpenSSH server, waiting for connections from VPN2.
First off, we need to enable tunneling support on the OpenSSH server, since this feature is disabled by default. This is achieved by setting the PermitTunnel parameter in /etc/ssh/sshd_config(5) to "ethernet", "point-to-point" or "yes", depending on whether you want the VPN to operate, respectively, at layer 2 of the OSI model, layer 3 or both.
[ ... ] # Enable layer-3 tunneling. Change the value to 'ethernet' for layer-2 tunneling PermitTunnel point-to-point
On the client side, the Tunnel parameter, in /etc/ssh/ssh_config(5), must be set to the same value as PermitTunnel on the OpenSSH server:
[ ... ] # Enable layer-3 tunneling. Change the value to 'ethernet' for layer-2 tunneling Tunnel point-to-point
Next, we need to enable IP forwarding on both VPN gateways, since they will have to perform routing of network traffic:
# sysctl net.inet.ip.forwarding=1
Uncomment the following line in /etc/sysctl.conf(5) to re-enable it after reboot:
net.inet.ip.forwarding=1
And the configuration phase is over: how could it be easier? Now we only have to force sshd(8) to reread its configuration file by sending it a SIGHUP signal:
VPN1# pkill -HUP sshd
Before actually firing up the VPN, we will carry out a couple of preliminary steps on both the OpenSSH server and the client, i.e. creating and configuring the tun(4) network device and setting up the appropriate routes to the remote network(s) and hosts.
VPN1# ifconfig tun0 create VPN1# ifconfig tun0 10.0.0.1 10.0.0.2 netmask 0xfffffffc VPN1# route add 192.168.0.0/24 10.0.0.2 VPN1# route add 192.168.1.0/24 10.0.0.2
VPN2# ifconfig tun0 create VPN2# ifconfig tun0 10.0.0.2 10.0.0.1 netmask 0xfffffffc VPN2# route add 172.16.0.0/24 10.0.0.1
Well, we're finally ready to initiate the ssh(1) connection and establish the VPN tunnel. The -f option requests ssh(1) to go to background after prompting for the password, and the -w option specifies the numerical ID of the tun(4) device in charge of forwarding VPN traffic; in our setup, we're using tun0 on both client and server, so we will set this option to 0:0.
VPN2# ssh -f -w 0:0 1.2.3.4 true root@VPN1's password: pAssWOrd
To finish, we will configure the client machine to automatically start the VPN on boot. To prevent the system from hanging during startup until the user enters the password, we need to create an RSA authentication key for the user with the ssh-keygen(1) utility:
VPN2# ssh-keygen -b 2048 -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): <enter> Enter passphrase (empty for no passphrase): <enter> Enter same passphrase again: <enter> Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: cd:9c:3b:3a:c0:92:7f:c2:9b:6e:3a:48:dc:50:a4:2a root@vpn2.kernel-panic.it VPN2#
and add the newly-generated key, contained in /root/.ssh/id_rsa.pub, to the authorized keys in /root/.ssh/authorized_keys on the server; please make sure that this file has restrictive permissions (600):
VPN1# cat authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAoWqL6wpgL5j3dlFtdYWT+cc72F/FtMhmTBLUEcCMQQy8 /V9CptSn7yCC+1R5xhZD8WO3d11c7R8pUHPP77A3omFruEpk4pREuisHnMtA6XyVFoxshhV1osyoQ/HJ w6BhTmmGDCCyNsPmQyAPi9V7rL4NNSlll6mFXqLDNth6wf0qjo33BURsyKR6xxmt5QBhDpCBDel3EwLh gE2Jy06XJZKa62/WU6ofbnXZWwGX8ZsbCPxqqu3EOBhMwlUgA1IgksGfOcB4rgV+qpcPUfl3fQM67Mc7 Nwhh7jqkaCTpu/vs4OpBFt6j9eVxMgRGylg4a9tBcZY2588wPZZThpx/sw== root@vpn2.kernel-pa nic.it VPN1# chmod 600 /root/.ssh/authorized_keys
Next, on the server side, we need to create the configuration file for the tun(4) pseudo-device, /etc/hostname.tun0, which will also include the necessary static routes:
10.0.0.1 10.0.0.2 netmask 0xfffffffc !route add 192.168.0.0/24 10.0.0.2 >/dev/null 2>&1 !route add 192.168.1.0/24 10.0.0.2 >/dev/null 2>&1
Similarly, on the client side, we will create the /etc/hostname.tun0 configuration file:
10.0.0.2 10.0.0.1 netmask 0xfffffffc !route add 172.16.0.0/24 10.0.0.1 >/dev/null 2>&1
but also add the VPN start command in /etc/rc.local(8).
[ ... ] echo -n ' OpenSSH-VPN' /usr/bin/ssh -f -w 0:0 1.2.3.4 true