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.