SSH over VPN with openconnect and ocproxy

by Martin Monperrus

I have a VPN access that uses the openconnect stack. I want to access a machine on the private network via SSH. However, I don't want to route all my traffic network through VPN. Here is the solution.

You need openconnect, netcat (nc) and ocproxy:

aptitude install openconnect ocproxy

Commands

The core idea is to combine VPN with Socks, such as only the traffic going through a Socks server goes to the VPN, and the rest remained untouched. Then, only simply tell SSH to use Socks. The combination VPN/Socks is done thanks to ocproxy.

Let's start, we run the VPN/Socks proxy on port 9052:

$ /usr/sbin/openconnect --script-tun --script "ocproxy -D 9052" vpn.yourdomain.fr 

Then, we configure SSH to use the Socks server using a proxy command.

// in $HOME/.ssh/config
Host myserver
  User martin
  ProxyCommand nc -X 5 -x 127.0.0.1:9052 %h %p

And finally, we can ssh over VPN on port 443:

$ ssh myserver

Refinements

If you want to connect automatically, you have to use in input pipe where the password is given by another program (eg taking the password in a safe or keyring):

/usr/sbin/openconnect --no-cert-check -u mmonperr --script-tun --script "ocproxy -D 9052" \
  vpn.inria.fr < <(mycommand-giving-the-vpn-password)

By default, openconnect does the VPN over UDP datagrams using DTLS. If you want to use TCP (or if you are forced to in a network where UDP is blocked), there is the option --no-dtls.

/usr/sbin/openconnect --no-dtls --no-cert-check -u mmonperr --script-tun --script "ocproxy -D 9052" \
  vpn.inria.fr < <(mycommand-giving-the-vpn-password)

Automation

This can be fully automated, for this, create a script called nc-openconnect to be used in SSH's config.

The script contains:

#!/bin/bash
# connects to SSH through openconnect and VPN
# for use iwth ProxyCommand in SSH

# first run openconnect
/sbin/start-stop-daemon --pidfile /tmp/openconnect.pid --make-pidfile -b -S --startas /bin/bash -- -c 'exec /usr/sbin/openconnect --reconnect-timeout 60 --no-dtls -u mmonperr --script-tun --script "ocproxy -D 9052" vpn3-sop.national.inria.fr < <(mycommand-giving-the-vpn-password)' &
sleep 2

# kill connection on exit
function cleanup {
  /sbin/start-stop-daemon --stop --pidfile /tmp/openconnect.pid
}
trap cleanup EXIT

# redirect traffic (standard input and output) through VPN
nc -X 5 -x 127.0.0.1:9052 $1 $2

Then, in .ssh/config,

Host foobar
  HostName 91.134.241.189
  User martin
  ProxyCommand nc-openconnect %h %p
Tagged as: