OpenSSH : Tunneling VPN
Introduction
Since version 4.3 of OpenSSH, the option to create IP tunnels has been added.
First, you need to check the OpenSSH version on both the server and client.
ssh -v
You need root privileges on both machines. There are operations to perform, both at the configuration and network levels.
Configuration
Server
OpenBSD
The first thing to do is to tell OpenSSH to authorize tunnels by adding this directive:
# Enable layer-3 tunneling. Change the value to 'ethernet' for layer-2 tunneling
PermitTunnel point-to-point
We need to ensure that forwarding is activated:
sysctl net.inet.ip.forwarding=1
And will be activated at reboot:
net.inet.ip.forwarding=1
Let’s create a tun interface:
ifconfig tun0 create
ifconfig tun0 10.0.0.1 10.0.0.2 netmask 0xfffffffc
And again, make the configuration permanent:
10.0.0.1 10.0.0.2 netmask 0xfffffffc
Now we can restart SSH:
pkill -HUP sshd ; /usr/sbin/sshd
You also need to disable privilege separation, or adjust permissions on /dev/tun
. For simplicity, I’ve added:
UsePrivilegeSeparation no
Another solution is to grant read-write permissions to a specific group on /dev/tun
, which is much simpler and safer.
chmod :mygroup /dev/tun
And of course, be in that group.
You then need to load the tun module:
modprobe tun
And add it to /etc/modprobe.preload
for loading at next boot:
echo tun >> /etc/modprobe.preload
Client
On the client side, we also need to add this directive but in the /etc/ssh/ssh_config
file:
# Enable layer-3 tunneling. Change the value to 'ethernet' for layer-2 tunneling
PermitTunnel point-to-point
Edit the /etc/network/interfaces
file and add this interface:
iface tun0 inet static
pre-up ssh -S /var/run/ssh-myvpn-tunnel-control -M -f -w 0:0 5.6.7.8 true
pre-up sleep 5
address 10.254.254.2
pointopoint 10.254.254.1
netmask 255.255.255.252
up route add -net 10.99.99.0 netmask 255.255.255.0 gw 10.254.254.1 tun0
post-down ssh -S /var/run/ssh-myvpn-tunnel-control -O exit 5.6.7.8
You only need permissions on /dev/tun
, so either run as root or have write permission on /dev/tun
, as mentioned above, then do (where client is the server):
ssh -w any:any client
You can look at the -f
and -N
options to avoid launching a shell on the remote machine. And of course, the usual options still work (key, tunnel, master/slave).
Then, as root, you can change the IP of the new tun0 interface on the server:
ifconfig tun0 10.0.0.1
On FreeBSD:
ifconfig tun100 inet 10.0.0.1 10.0.0.2 netmask 255.255.255.255
And do the same on the client:
ifconfig tun0 10.0.0.2
or
ifconfig tun100 inet 10.0.0.2 10.0.0.1 netmask 255.255.255.255
Finally, you can now test the ping from the client:
ping 10.0.0.1
The rest is normal interface configuration. You can add routes, a firewall, anything.
However, you should know that TCP connections over TCP (as is the case with SSH) are not recommended, due to the nature of TCP.
FAQ
Connection closed by …
This is generally due to the server struggling. Check that it has the correct DNS settings and that in the configuration (/etc/ssh/sshd_config
) the LoginGraceTime value is high enough.
Cannot fork into background without a command to execute
You may encounter this error message:
Cannot fork into background without a command to execute
Failed to bring up tun1.
To resolve this issue, add the -N
option to the SSH command.
Resources
Last updated 14 May 2010, 22:46 CEST.