Last Updated:

Yubikey and 1FA, 2FA, MFA with SSH

operationroot FIDO

A curated link selection of "HOWTOs".

I was going to write a guide for you but in the end realized there are just too many different ways to use a Yubikey with SSH. Some needlessly complex in my view, others elegant but barely supported. So instead I will try to assemble a list of useful and accessible guides for each of the various ways you could use your Yubikey with SSH and try to explain applicable pro and cons as I see them.

But before we start you may find this Yubikey Cheatsheet useful.

The Yubico PAM module

This probably the easiest way to integrate OTP based authentication with your Yubikey and SSH.

Using Yubico's infrastructure

What the above guide does not address is, what if the Yubico infrastructure for some reason cannot be reached. Then your server would not be able to authenticate you and you'd be locked out.

https://www.linode.com/docs/security/authentication/how-to-use-yubikey-for-two-factor-ssh-authentication/

or a different shorter example here:

http://jornane.me/doc/yubi-ssh/

This other guide addresses this issue by instructing PAM to ignore the Yubikey authentication if the API cannot be reached by pam_yubico. The module will return AUTHINFO_UNAVAIL to PAM, which can then be acted upon. Note this is a Gento guide. So for Ubuntu you'd have to add the relevant code to /etc/pam.d/sshd either before or after @include common-auth depending on whether you'd like password or yubikey OTP to be requested first from the user.

auth    [success=ok authinfo_unavail=ignore new_authtok_reqd=ok ignore=ignore default=bad]    pam_yubico.so id=client_id key=secret_key authfile=/etc/ssh/authorized_yubikeys debug debug_file=/var/log/auth.log

default=die vs default=bad is the difference between required and requisite PAM statements. Depending on your view on this, one could create a side channel leak by confirming which Yubikeys are valid on the system. By changing success=ok to success=done and doing the same for new_authtok_reqd you'd turn this into an optional statement (control value) and essentially make this setup 1FA.

Now this approach of course means that an attacker could "downgrade" your 2FA to 1FA by simply DDoSing the Yubico Cloud authentication service as this exchange reminds us. (It also points out that Yubico's pam module will only return AUTHINFO_UNAVAIL if their servers can't be reached, but will hang and wait indefinitely if the server simply fails to respond due to the lack of support for a timeout facility.)

To mitigate against this, two possible options come to mind:

  • Use another cloud authentication service (e.g. google authenticator as your fall back option. The configuration for this below is adapted from this guide. It will ask for the user password first then either use the Yubikey for the second factor or google authenticator as the fallback.

sudo vi /etc/pam.d/sshd@include common-authauth       [success=done new_authtok_reqd=ok default=ignore] pam_yubico.so id=client_id key=secret_key authfile=/etc/ssh/authorized_yubikeys debug debug_file=/var/log/auth.log nullokauth       required     pam_google_authenticator.so

  • Or you detect that Yubico's authentication service is currently not available and switch all accounts to using ssh key files as a mandated second factor during the outage. I will publish a guide on this soon.

Using your own infrastructure

The servers (modules) behind Yubico's cloud based authentication service are also available for your own on premises implementation should you wish to do this.

Why? Well theoretically a DDoS attack could make Yubico's servers unreachable or slow to respond, thus impacting your ability to access your own servers, depending on how you chose to configure things as outlined above. Also theoretically Yubico will know that your organization is authenticating logins and theoretically they also know which keys they sold to you, so theoretically (again) the/a government could lean on them to disable your keys and thus lock you out of your own machines.

Now until the Huawei saga unfolded I would have consigned the above concerns firmly to the land of fiction. However, you may find yourself in a country or organization that suddenly have export restrictions placed upon them and could thus be cut off from Yubico's cloud auth wholesale. So running your own, locally, might be useful after all.

This well illustrated guide blow shows how to host your own Yubico style authentication infrastructure:

https://www.kilala.nl/Sysadmin/index.php?id=2340

Should you prefer to use a different OTP authentication solution, a good example which is also available in a very capable community edition and capable of supporting Yubikeys among many other solutions is the privacyide3a authentication server.

https://www.privacyidea.org/about/features/

Using U2F with SSH

Yubico's libpam_u2f only supports reading the Yubikey via USB. This makes it unsuitable for remote logins via SSH. However, there are ways to use U2F for remote logins through other means.

OpenSSH

Strangely enough, the most obvious and elegant way to do 2FA with SSH is the on that is not officially supported. The post linked below explains how to do this.

https://www.nomachine.com/AR09P00996

This relies on a patch for openSSH but has only been tested with a now very out of date version (6.7p1). See link below for the patch.

https://bugzilla.mindrot.org/show_bug.cgi?id=2319

Sadly 5 years on, not much seems to have happened in terms of progress. Reading through some of the mailing list history it also seems that at the time the openSSH project, like many others, seemed to have been not the most welcoming or enthusiastic to new contributors, which is really both a shame and wasted opportunity IMHO.

So given the security implications of running a very out of date version of SSH vs. the benefit of gaining convenient 2FA capability for remote logins, I'd "suggest" you don't use this in production. If you hold sway with the openSSH team, maybe politely suggest that they'd give this a fresh look...

Teleport

If you are using the ssh security gateway/ssh server Teleport instead of openSSH as an intermediary to access your machines, then you are lucky in so far that U2F support has been built in since 2016, and no patching of old openSSH versions is required to enjoy this convenience.

Using U2F and an external web based authentication provider (a creative idea)

This is a rather interesting option to enable U2F 2FA for openSSH by having the SSH server provide a unique, use once, weblink to visit and execute the U2F verification with, during the login process. My description won't do it justice so please take a look at their site, video and documentation via the link below.

https://blitiri.com.ar/p/remoteu2f/

The git repo for this project can be found here and setup instructions can be found under the link below.

git clone https://blitiri.com.ar/repos/remoteu2f

https://blitiri.com.ar/git/r/remoteu2f/b/master/t/f=INSTALL.md.html

While this approach is unusual and maybe also a bit quirky it could be useful in desktop environments where a web browser is readily available alongside the shell window. That said I don't see any reason why a correctly configured android phone with an NFC enabled Yubikey cloud not be used to provide 2FA and inherently also "out of band" authentication in a text only ssh environment. Think forwarded or multi hop sessions from e.g. IoT devices.

Using the PIV smart card function

In this case the Yubikey acts like a PIV compliant smart card and its presence will be required in the machine running the SSH client. The following algorithms are supported as per the manual for version 5 Yubikeys:

  • RSA 1024
  • RSA 2048
  • ECC P-256
  • ECC P-384

One obvious and increasingly glaring shortcoming of this approach is that only 2048 bit RSA keys are supported or some elliptical curves that are not considered safe options in the ECC suite. Please take a look at this site for a more in depth evaluation of the supported curves.

Anyway, PIV is still deemed good enough for many US government departments, so if you decide it's good enough for you, here's a decent guide for how to set this up.

https://blog.habets.se/2016/01/Yubikey-4-for-SSH-with-physical-presence-proof.html

Using the PGP smart card function

Yes I realize PGP is wonderful but it also still suffers from a distinct last century approach to usability and may represent to much of a learning curve for some. Of course the reward is, that if mastered, your Yubikey can then also be used to do such things as sign your git commits etc.

Unlike PIV, this smart card variant supports RSA keys up to 4096 bits.

Below a link to one of the better guides I found on this subject.

https://www.isi.edu/~calvin/yubikeyssh.htm

Not using a Yubikey at all for 2FA

That's right, there are other options such as google authenticator that are available as mentioned above. But you can also simply require your users to use both a password for SSH and a key file. Making this an AND not OR requirement.

And I don't mean a password protected key, that's not a second factor but simply an additional security measure on one of the factors that protects it when lost or falling into the wrong hands, at least for a little while... depending on password complexity.

Here's how to configure openSSH accordingly.

https://systemoverlord.com/2018/03/03/openssh-two-factor-authentication-but-not-service-accounts.html

Not using SSH, just logging on locally

Just as in the post about using U2F to protect sudo locally, libpam-u2f can also be used to log you onto your system locally. Simply refer to the official Yubico guide for this.

https://support.yubico.com/support/solutions/articles/15000011356-ubuntu-linux-login-guide-u2f 

What about MFA?

Nothing is stopping you from combining some of the methods above to make your authentication requirements mutli-factor: SSH keys, password, Yubikey. Or how about password, google authenticator and yubikey? The combination of methods is up to you.... go for it!

What else?

You may be aware that your Yubikey has two slots that can be accessed through a short tap and a 3 second long tap respectively. This post provides a good example how to make use of this capability for OTP in practice.

So I hope you found something of use in this link collection. Should you have suggestions for another method that ought to be included here, please feel free to get in touch and let me know.