We've been using Duo Security for two factor ssh auth[0] for a number of years. Its quite easy to setup and gives you push notifications to your phone. Its awesome.
Duo's PAM module arguably violates the "MFA is only useful, if all parts of it can be enforced server-side!" principle from this blog post. The authentication does happen on a server, but it's a server controlled by Duo, not by you. The PAM module simply makes an API request and authorizes a user iff Duo says they should be authorized.
(Hopefully you'll have configured things so that Duo's approval and a password are both required for login, so this isn't a catastrophic break in security, but it's still a little worrying. And what about when your Internet connection, or Duo's, is having problems? As I write this comment, HTTPS connections to www.duosecurity.com are throwing errors because they've installed a certificate for *.test.duosecurity.com. [1])
I prefer Google's pam_google_authenticator module. Like the Android/iOS app, it doesn't have any external service dependencies; all it assumes is reasonable clock synchrony.
Sterling Windmill from Duo Security here. We experienced a brief issue today resulting from the deployment of an incorrect SSL certificate to our public website. One benefit of the conscious decision to segregate our public website from other services is that this event had no impact on end user authentication. Feel free to reach out to support@duosecurity.com with any questions regarding this or anything else!
From the article: "You should not publicly expose SSH on any server, if you can avoid it! The vast majority of your estate would of course be locked away and protected by some sort of proper VPN (IPSec, OpenVPN etc), wouldn't it?"
I'm curious about more details -- to what degree is SSH (with public key auth only of course) more vulnerable than VPN, and for what reason? From academia I'm used to access to computers around the world using public SSH and port forwarding for most things, and in my world VPN was something people used on Windows, or just because it lets desktop applications act more normally, but I didn't think there was a security difference...
The author goes into this in the beginning by stating that the admin can have "PasswordAuthentication no" in sshd_config and users with keys can still have weakly protected (or unprotected!) keys.
In other words, you can lead a correct horse battery staple to water, but you can't make it protect its key pair with a strong password.
That's a separate issue though. You can have weak/unprotected VPN keys as well.
I think the author's argument about using VPNs is more a "right tool for the job" thing. SSH is fine for remote shell, but then you start to need other network service access. You can use SSH tunneling, yes, but a VPN is better suited.
So, in a nutshell, the point is "only expose a single service." And since a VPN is more flexible than SSH, might as well go with that if you have the choice. You can of course make counter arguments along the lines of "expose only the minimal amount of functionality" or whether you think a VPN or SSH is more secure.
A VPN will allow you to tunnel all of your traffic over a secure connection.
In SSH, you can tunnel ports, but that only secures traffic at that port.
You can use a SOCKS proxy, but that only secures traffic configured to go through it.
You can use the -w option and use IP forwarding, but then you're running TCP/IP over the SSH protocol which is bad. This is the closest you'll get to emulating what a VPN provides.
I think the question is not, should you use SSH as a makeshift VPN, as that answer is more obviously "probably not". The harder question is, is it better to VPN in before connecting to SSH, and present MFA at the VPN and SFA at the server, or is it better to expose SSH directly and perform full MFA directly at the SSH endpoint?
What do you trust more, OpenVPN with a port forward to an SSH server behind it, or a directly exposed SSH agent? Which will properly authenticate users without exposing any possible auth bypass, RCE, DoS, side channels, or potential vulnerabilities?
In general it's best if you can assume a perimeter firewall (i.e. VPN) will not always succeed in keeping the bad packets out. Of course it's a cop out to simply say "do both".
In general if you are managing a larger number of servers, it's not practical to MFA to each one individually / interactively. So you are forced to MFA to the border, and SFA to the individual servers. If you have a small number of servers you may find you get more fine-grain control, better auditing, and fewer points of failure to do something like this article suggests -- skip the OpenVPN and implement fully server-side validated MFA directly to the server.
The ultra-paranoid would add an HMAC based port-knocking scheme and forget about primitives like fail2ban. This could either be based on a 3rd factor or reusing the existing private key.
Thanks, this was a good answer. Yes, I am going to want to use SSH in the end, the console is typically what I want, potentially with a single port forwarded (8080 or whatnot), so I guess the question really comes down to "is there any reason to believe there are more exploits in OpenSSH than in VPN", and possibly also "is it so hard to configure and keep updated a Linux box with OpenSSH correctly that it is better to go with VPN".
OpenSSH has had critical vulnerabilities in the early 2000's, but it's held up extremely well the last 10 years. OpenVPN has a significantly higher attack surface, especially if you consider things like XSRF on the Admin GUI. You'll almost certainly need a hardened and updated OpenSSH in any case, so using a VPN can only possibly increase your attack surface.
My own opinion is if you have few enough servers and no other reason for a VPN, then expose SSH on a non-standard port or use a port knocker, and use something like this article's MFA solution.
The non-standard port or port knocking is really just to keep spam out of your logs. Since authentication requires a 4096 bit private key, you're not worried about brute force in any case.
Google Autenticator can't be bypassed by someone with access to Google's systems. Duo's two factor auth can be bypassed by someone with access to Duo's systems.
For what it's worth, I agree that Duo has better usability, and is probably the better solution in most cases. TOTP is the more paranoid option.
I believe that Google Authenticator uses TOTP. Six digit HMAC-SHA1 TOTP from a base32 encoded secret using a 30 second timestep. At least, that has been my experience. I wrote an OATH client and it works with Google Authenticator using those parameters. https://github.com/w8rbt/oathgen
Duo supports this as well (and also other TOTP/HOTP modes). If you have access to a Duo account, look at the 'Import Hardware Tokens' feature under 'Devices'. That's not named accurately. Really it should be named, 'Import TOTP/HOTP secrets' as that's what they ask you to import and those secrets can be used in OATH compliant HW fobs or any software that does standard TOTP/HOTP. They also allow you to import Yubikeys as well if you like (of course, that's not OATH).
TOTP relies on a shared secret. With Google Authenticator, the secret is shared between your phone and the SSH server you're logging into. With Duo, the secret is shared between your phone and Duo's API backend; the server has no independent way of authenticating it.
Authorization is done by making a POST request to a Duo-controlled server. If the response is the string "allow", it lets you in; if it's "deny", it doesn't. Duo can make that server return whatever they want.
Sorry for the late reply. You can basically set up to send yourself an SMS with codes that you can use offline I think. Actually, I am not quite sure if they would work offline. So I think you are right. Sorry.
Now, some people argue that a password-protected SSH key pair consitutes MFA, with the key pair being the "what you have" and the password protecting it being the "what you know". Well, it is wrong and dangerous!
No. It is fundamentally correct. The user can always do all kinds of stupid things to undermine the security of services they can access. For example transfer their token from a separate device (phone) to a generator on the same computer they use to log in (there's even a Chrome addon somewhere), or store passwords in a sticky on the screen... the possibilities are endless.
Still a good article on your MFA options with ssh.
Right, it is wrong and dangerous, but not for the reason the article claims. The user can always do something stupid to compromise their security, but if they just do what they're advised to do (store their token on their phone), then with proper 2FA, the attacker has to compromise two systems (the computer with the terminal and the phone with the TOTP secret) to gain access. With SSH passphrases, only one system needs to be compromised (the terminal).
That one seems to recommend the OATH-toolkit, I tried it once and the documentation wasn't impressive (shocker!) and I was concerned about the security aspect as well. I wonder if anyone has audited that code properly?
Google Authenticator PAM module seems to be the other option that is widely used and it's much easier to find information on it.
What about when your users start storing their passwords in a password manager app? Which is on both their smartphone and their laptop? (And it's possibly only encrypted when they are logged out - i.e. hardly ever)
The point being that users are already turning something-you-know into something-you-have by using a password manager.
EDIT I'm not saying that password managers are a bad thing.
We use fwknop (time-based, single-packet, single ip, port knocking with gpg keys) + monkeysphere (ssh keys stored in gpg) + Google Authenticator on FreeBSD with PF enabled in addition to Security Groups on AWS.
https://jumpcloud.com/blog/sharing-google-authenticator-secr...
If you are interested in setting up 2FA for SSH, we have a great step-by-step guide for multi-machine deployments. Alternatively, you can sign up for JumpCloud to automatically implement this, and manage other key aspects of your infrastructure.
I'm using yubico-pam (https://github.com/Yubico/yubico-pam) module for a bit over a year now on our controlling servers as well as my own, so that we can use Yubikeys for authentication. Works extremely well so far.
That's still two factor authentication. The possible factors are "something you know", "something you have" and "something you are". Two "things you have" only count as a single factor between them.
Generally, "something you are" is some sort of biometric. Fingerprint, iris, hand geometry, palm veins, face and voice are all possible. Some laptops have fingerprint readers, face/voice recognition would probably work fine through a cheap webcam. I'm not sure how you'd prevent replay attacks if you were running it over the internet.
For single or small-n user systems, the best practice that's evolved around this is to not actually send the fingerprint image to the remote server. A trusted security module has a private key and the biometric sensor, and the remote server has the public key. The trusted security module locally validates the fingerprint, and then signs a message that can't be replayed to indicate the fingerprint was presented.
[0]: https://www.duosecurity.com/docs/duounix