These are the requirements for our VPN setup:
- We must be able to use a given laptop with a strict policy (ie. we cannot install any third party applications, including VPN clients..). Luckily, putty is an approved application for these laptops.
- Two factor authentication
- Full control over which services are available to a VPN user.
- Log facilities (user logins) .
With these requirements in mind, we decided to implement a solution based on SSH and WiKID.
Our initial plan was to have an SSH server we could log into from an un-trusted network, and then tunnel a connection to an RDP/VNC session on the user's dedicated workstation at the office. In essence, something like this:
Home -> SSH -> Workstation
Since we need full control over what the user's allowed to do on his VPN connection, we can't use a simple 'ssh -L5901:workstation:5901 user@company.com', as the user might attempt to connect to other services (eg. another user's workstation).
So, in order to control what a user wants to forward when connected to a SSH server, we will be using the ~/.ssh/authorized_keys file and the permitopen=-directive, and thus require public key authentication.
However, we were not able to make a single SSH instance require authentication against both PAM and public key. So, we ended up running two SSH-instances - one instance accepting only public keys (eg. on port 22/tcp), and the other (eg. on port 2222/tcp) authenticating only using PAM. In order to force the user to connect to the second SSH instance, we used the command=-directive in authorized_keys. So, now we had something like this:
Home -> SSH (Public Key Auth.) -> SSH (PAM/WiKID Auth.) -> Workstation
The ~/.ssh/authorized_keys for a user would look similar to this:
permitopen="localhost:3010",command="/usr/bin/ssh -p 2222 -L3010:workstation:5901 user@localhost \"echo 'Connected. Press Enter to close tunnel'; read\"" ssh-rsa AAAAA[...]
The VPN user would set up his forwarding like this:
ssh -L5901:localhost:3010 user@company.com
..which would be the only allowed forwarding, and he should be able to connect to his VNC session at the office workstation using 'vncviewer localhost:1'.
This solution might not scale that well though, as it requires a unique port (such as the localhost:3010) for each service a VPN user should be allowed to access. But, in our case it's sufficient.
Here are some config highlights:
/etc/ssh/sshd_config for SSH accepting only public keys:
[..] Port 22 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_dsa_key PubkeyAuthentication yes PasswordAuthentication no UsePAM no [..]
/etc/ssh-forward/sshd_config for accepting only PAM auth. (radius/wikid)
[..] Port 2222 ListenAddress 127.0.0.1 HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_dsa_key PubkeyAuthentication no UsePAM yes [..]
We also made a few changes on /etc/pam.d/ssh to make sure the second SSH instance would only accept radius auth. and not fall back on any other mechanism.
/etc/pam.d/ssh:
# Radius authorization auth required /lib/security/pam_radius_auth.so # Standard Un*x authentication. #@include common-auth <---- Disable common-auth
That's pretty much what we did, on a Debian Etch installation. Hopefully, this would be useful to someone else as well :)
The author of this how-to wished to remain anonymous.