Automatic VPN login on connect with ssh and vpnc
Establishing a VPN connection is usually a pain. They time out and close and, at least for me, are never up and running when you need them. I use VPN primarily to ssh into systems and because openssh is one of the most flexible pieces of software on the planet there is naturally a way to automate the VPN connection. Here we will use the ProxyCommand ssh config setting to establish a vpn session behind the scenes when we ssh to a machine.
What is a ssh ProxyCommand?
The ssh_config man page tells us that… “ProxyCommand specifies the command to use to connect to the server. The command string extends to the end of the line, and is executed with /bin/sh. In the command string, ‘%h’ will be substituted by the host name to connect and ‘%p’ by the port. The command can be basically anything, and should read from its standard input and write to its standard output. It should eventually connect an sshd(8) server running on some machine, or execute sshd -i somewhere. Host key management will be done using the HostName of the host being connected (defaulting to the name typed by the user). Setting the command to none disables this option entirely. Note that CheckHostIP is not available for connects with a proxy command.”
In other words, we can run an arbitrary command before ssh establishes its connection. Perfect! The only drawback is that ssh expects this command to be able to carry the ssh connection. Not a problem, we can script that.
Tying it all together
This script is very easy, and only supports a single VPNC session at a time, but it is a good start for you to extend upon. This belongs in the .ssh/config file located inside your home directory. If the file or directory (or both) don’t already exist just create them.
Normally I would connect to the VPN manually using a VPNC configuration profile named ‘myvpn’ (which is located in /etc/vpnc/myvpn.conf).
~# vpnc myvpn VPNC started in background (pid: 4579)...
To automate this, we will place the VPNC command into the ProxyCommand string as well as a small test condition to determine if a session is already running. Additionally, we need to include the nc command string. This is so that ssh can pass data through to the host after the command has been run. Finally, I have redirected stdout for VPNC to stderr so that it is printed to the terminal while being used as a ProxyCommand.
#~/.ssh/config Host 192.168.10.* ProxyCommand bash -c 'if ! pgrep vpnc; then vpnc myvpn 1>&2; fi; nc -w 60 %h %p'
You can specify the host using an IP range (as demonstrated above) or via host names. I find IP addresses easier simply because I can wildcard the whole VPN range.
Here is what a ssh connection looks like with the updated .ssh/config
# gw2:~# ssh email@example.com VPNC started in background (pid: 5091)... Last login: Thu Jul 15 12:40:19 2010 from 172.16.1.11 [root@host ~]#
And upon subsequent connections while the VPN is established…
~# ssh firstname.lastname@example.org email@example.com password: Last login: Thu Jul 15 12:40:48 2010 from 172.16.1.11 [root@host ~]#
As you can see there is no output from vpnc, this means that the existing VPN session is being used.
There is much more you can do from here to further automate the process and implement more robust session detection and concurrency. Happy hacking!