Two Factor (2FA) SSH Authentication Using YubiKey

3 minute read

The Yubikey works by taking an AES-128 encrypted message and sending it Yubico’s authentication server. If the AES private key is stored on Yubico’s server and the contents of the encrypted message are validated (counter, serial no, etc) then a verified result is returned, else fail.

The Linux PAM module will use the result to allow access to the machine in addition to a user’s regular password.

A user would use the 2FA (two factor authentication) system by sshing in to a remote machine, typing their password followed immediately by the YubiKey’s encrypted message (modhex encoded). If everything checks out the user is permitted access and the rest of the session continues as normal.

At the same time, if the user elects to use a ssh private key (think automation) the login process is unaffected by the YubiKey.

These are my brief notes on my YubiKey authentication setup on Arch Linux.


  • A physical YubiKey, I have the YuibKey Standard. Thinking about a Neo.
    • YubiKey is configured for Yubico OTP which is the default for slot 1 (aka short press).
    • The Yubikey needs to have its Yubico OTP AES key uploaded to YubiCo’s authentication server.
    • Test all of this Yubico’s Demo Site
    • YubiKey public ID, available from the demo site or by reading the first 12 characters of short press (ie run head -c 12 in the console and then press the YubiKey).
  • Necessary libraries and dependencies installed, for Arch users it’s as simple as:

    yaourt yubico-pam-git

System Modifications

These steps were run on an Arch Linux machine and are likely slightly different for every other distro.

  1. Modify /etc/pam.d/system-remote-login to match the following, note the addition of the line:

    auth      required id=1
    auth      include   system-login
    account   include   system-login
    password  include   system-login
    session   include   system-login
  2. Create a ~/.yubico/authorized_yubikeys file for each user with the following format:

    <username>:<yubikey id from pre-reqs>
  3. Attempt to ssh in to the local box ssh [email protected] and type the user’s password followed by a short YubiKey press. The system should login.
  4. Whenever configuring PAM, verify that security isn’t broken. Try typing no password, wrong password, with/without YubiKey, with/without authorized_yubikeys file, with invalid entry in authorized_yubikeys file. Also be cautious of ssh multiplexing (connection sharing) as it may skip authentication and re-use / multiplex an existing connection. This could be misleading.


If the above steps don’t work, turn on debugging:

  1. Add debug option to the end of the line in /etc/pam.d/system-remote-login

  2. Create the debug log file:

     sudo touch /var/run/pam-debug.log
     sudo chmod go+w /var/run/pam-debug.log
  3. Tail the logs looking for clues while debugging:

     sudo journalctl -f -l
     tail -f /var/run/pam-debug.log
  4. Disable debugging by removing the debug option and removing the log file.


Security Implications

Compromising the Added Security

The security is at least as strong as the original password, the second factor could be bypassed in the following cases:

  • The AES private key of the Yubikey is compromised. Could be compromised by a very sophisticated via side-channel attack or if the key was regenerated or submitted to Yubico insecurely using YubiKey Personalization app.
  • An adversary installs a trusted CA on the target machine and performs a man-in-the-middle attack when the pam_yubico modules contacts Yubico.
  • An adversary could modify ~/.yubico/authorized_yubikeys.
  • If the PAM files were incorrectly modified all security could be compromised (test!!!).
  • Would be locked out of remote ssh access if Yubikey’s authentication web service goes down. Moot point is would also be locked out if the remote machine’s Internet connection went down, but that would cause many more problems like… no ssh access period.


  • Bruteforce attack is significantly harder without forcing users to memorize something obnoxious.
  • Can’t be keylogged and replayed on a compromised machine due to the embedded counter.
  • Doesn’t require the user to expose a private ssh key (where both the key and passphrase could be stolen) when logging in from someone else’s insecure machine.
  • Impossible to login to users on the remote machine without configuring ~/.yubico/authorized_yubikeys. This prevents the accidental creation of ssh accounts when trying to create a simple user account.


  • Now very difficult to login on a cell phone, but could be worked around with a dedicated ssh private key.
  • The user can’t lose the YubiKey and the (hopefully) installed ssh private keys at the same time or the user will be locked out.