From what I know, you can't implement every feature you require without custom / commercial products to lock down everything.
Here are some thoughts to keep in mind while elaborating on how to meet the required critera:
Typical VPN-solutions add routes. For routes to be added, the user needs to have administrative rights on the client computer. This isn't always the case, especially when using hardware provided by the employer.
Depending on the implementation, existing VPN-solutions have their workarounds regarding that topic. As far as i know, OpenVPN registers a Windows-service while installing the client, which adds the routes as requested by the actual client operated by the user.
Tunnelblick (an OS X client for OpenVPN) also does some voodoo to get the routing to work, and at some point needs administraive rights as well.
OpenVPN therefore at least needs some effort while configuring the clients to work around that issue.
Since at least OpenVPN can add the routes "post-connect", the user could actually add additional routes by himself. Lets say the OpenVPN server pushes routes to a few hosts that should be accessable through OpenVPN. This results in the client adding the routes to those hosts. There's no mechanism prohibiting a user from adding even more routes to additional hosts. So if those routes actually are vaild, access to not authorized backends would be possible. To prevent this, the firewall on the server would have to be airtight to not allow anything but traffic to allowed hosts.
If the infrastructure you want to provides has to be available to employees that are often accessing the server from hotels, VPN might be not usable at all. There are quite a few hotels which don't forward the traffic needed for VPN connections. In some cases, just ports 80 and 443 are allowed.
Moving away from my OpenVPN thoughts, your requirement to only allow connections from "trusted" devices is not possible as far as I can tell. This would be implemented through a firewall (usually iptables in case of CentOS).
The rule that you desire would
DROP packets from untrusted devices. Unfortunately, iptables has now way of checking if a device is trusted or not, since such information is not part of the packet. Although there are solutions to filter in a similar way at least within a compatible network (ask Google for PitBull Foundation by General Dynamics if you are interested in this topic).
Now moving to thoughts on how I would actually implement your scenario, although lacking some of the required criteria.
First of all, OpenSSH is not a VPN solution. It is able to establish a VPN-like tunnel, but to my knowledge, other VPN solutions are superior to the OpenSSH approach regarding performance and functionality.
Having said that, you mention, that the users typically will just be using http/https services. Those can easily be accessed through SSH tunnels without any VPN-like functionality. I won't go into great detail on how to configure this, but I'll point out the general approach using OpenSSH.
The first thing that might make sense would be to configure the SSH daemon to use port 80 or 443. This would enable users the connect to the server from almost anywhere, even hotels.
Regarding security, the sshd configuration allows to add rules matching users, hosts etc. This means, you can actually limit the users traffic to specific hosts behind the OpenSSH server without having to filter this in the firewall. Such a rule could look like this:
Match User JohnDoe
PermitOpen internal.resource:80 other.internal:443
Secure authentication is mandatory. OpenSSH can make use of PAM modules to authenticate the user. There are several possibilities like authenticating against LDAP, Radius etc. A nifty solution that uses 2-factor authentication in a simple way would be to use the Google Authenticator, which has a PAM module as well. There are several resources pointing out on how to configre OpenSSH to use the Google Authenticator.
Actually the hardest part when using this solution would be what happens on the client-side. The client would need a SSH-client which supports the usage of tunnels. On top of that, the client would have to know how to use the client and how to connect to the established tunnels. I open my tunnels manually from shell, but the typical user possibly won't be capable of such tasks without training. At first glance, this client might be of use: Auto(matic) SSH Tunnel Manager
To match my suggested solution to your requirement-list:
- All request would go through the SSH tunnel. Just one port of the SSH-server would have to be accessable through the internet. Check.
- If you just create and allow those 20 users, no one else can connect. Check.
- If configured correctly, users won't get a shell. A shell is not needed to establish tunnels. Check.
- Using 2-factor authentication would be my suggested alternative, but you could also do pubkey-authentication, with on key per device. But: those keys can be transferred to others devices. So without any further research: No check, but traffic could be limited to http/https.
- root, or whatever user is specified, could be configured to get a shell upon connecting. Check.
- Not possible.
- In case of my solution it's not "VPN", but yes, access would work that way. Check.