Wednesday, April 17, 2013

Non-root SSH VPN

There are networks where VPN protocols are filtered, but SSH is allowed through. There are various places that describe SSH VPNs such as, but most require allowing SSH root logins, and I'm not about to allow that.  I do assume one can sudo on the client, and have someone create the non-root tunnel on the server. ssh has a "-w" that "Requests tunnel device forwarding with the specified tun(4) devices between the client (local_tun) and the server (remote_tun)." One can create a tun device on Linux that is owned by a non-root user via the iproute2 command.  There is an excellent post on this at and its owner was a great help to me. I'm connecting a Mac to an Ubuntu machine; the incantations will vary a little if you choose different Unixs. The iproute2 that comes with Ubuntu 12 isn't new enough, so I grabbed a newer one and built it:
# does not do the trick, too old.
server$ iproute2-3.7.0$ ip -V
ip utility, iproute2-ss111117

# is new enough
server$ iproute2-3.7.0$ ip/ip -V
ip utility, iproute2-ss121211
What's up with those version numbers by the way? Regardless, here is what the two machines initially look like

One can create an non-root tun via
server$ sudo iproute2-3.7.0/ip/ip tuntap add dev tun9 mode tun user YOU group YOU
I picked 9 for no particular reason I can recall. After creating the tun device, the machines look like

One can list all the tun devices via
server$ sudo iproute2-3.7.0/ip/ip tuntap list
and delete them via
server$ sudo iproute2-3.7.0/ip/ip tuntap del dev tun9 mode tun
Now, let's assign the two IP addresses to the tun device
server$ sudo ifconfig tun9 pointopoint up
Note, the is an unused address on the server's LAN, and the is an RFC 1918 private address -- it can be any unused IP address and there's no reason to assign it to either of the client's or server's IP address ranges. Now we have

Make sure the server is routing
server$ cat /proc/sys/net/ipv4/ip_forward 
The final step on the server is to tell the arp daemon to respond to requests for the client VPN IP address
server$ sudo arp -sD eth0 pub

On the client, we first connect via ssh
client$ sudo ssh -vvv -w 0:9 YOU@
This has debugging cranked way up; once things work for you, you can turn this down of course. On the client, in a different window, assign the tunnel endpoint to the IP address you chose on the server LAN
client$ sudo ifconfig tun0 up
Add the fact that the server LAN IP address is the gateway to all of the server LAN
client$ sudo route add -net 5.6.7
and you're set -- you should be able to connect to any machine on the server's network.

Now things get a little tricky. You want to make the gateway on the server network be the default gateway to complete the VPN. First though, one must tell the client to continue to use its own gateway to get to the server and not use the default
client$ sudo route add -host
Now, you can set the default gateway for the client to be the default gateway for the server
sudo route add default
Here is how things now look

and you're done. Teardown is the opposite, as they say. This is all a little tricky and requires a little routing magic, but it's useful when SSH is all you have.


Unknown said...

Nice, but, if I can't access the server as root, very likely I cannot access it via sudo either.

Steve Beaty said...

That is true -- I assume a friendly sysadmin to set it up initially.