CentOS: Requiring a Yubikey OTP for SSH Password logins

This documentation was written in 2014. A more up to date version can be found in CentOS 8: Requiring a Yubikey OTP Press for SSH logins


The increasing ubiquity of the Yubikey makes it an ideal candidate for a Two-Factor Authentication mechanism, and configuring a CentOS based server to require a push of a Yubikey is particularly easy.

By the end of this documentation, we'll have configured a CentOS server to require that a user provide the following in order to login via SSH, unless they already have a valid RSA key pair configured on the server

  • Username (obviously)
  • Account password
  • Valid Yubikey OTP

For the sake of this documentation, we'll assume that you're using Yubico's validation servers (Yubicloud) rather than running your own (though if you are doing the latter, there's only one change in the configuration).




You'll need the following

  • Your YubiKey's ID
  • A Yubikey API credential pair
  • Root access to the server


Finding out your Yubikey's ID

If you don't already know the ID of your Yubikey, visit their demo page and give your Yubikey a quick press, the resulting page will include a 12 character string labelled 'Identity'. Make a note of it 


Getting an API Credential Pair

Your server needs to know a shared secret in order to communicate with Yubico's API, so visit the credentials page - https://upgrade.yubico.com/getapikey/ - and generate a set of credentials.



Installing the Libraries

We need to install a couple of libraries on the server, but as they're in the repo's it's fairly straight forward

yum install pam_yubico ykclient

Now, for sanity's sake, we'll double check the library was actually installed

find / -name pam_yubico.so

You should receive a hit, though it's exact location will vary by the version of CentOS you're running


Configuring a User to use the YubiKey

Next we'll configure one of our user accounts to use a Yubikey, in preparation for the changes we'll be making to SSH. Replace the username 'ben' with the relevant username below, and insert your Yubikey ID into the yubikey variable

Note: if you're running the commands below as the target user, you don't need to worry about the chown at the end

mkdir ~$OURUSER/.yubico
echo "$OURUSER:$YUBIID" > ~$OURUSER/.yubico/authorized_yubikeys
chmod 700 -R ~$OURUSER/.yubico

That user account is now configured to work with that specific Yubikey. However, SSH doesn't know about the yubikeys yet, so we need to configure that next


Configuring PAM

Next we need to configure PAM so that authentication takes the Yubikey into account. This is where you'll need to enter the API credentials that you generated

nano /etc/pam.d/sshd

# Find the line
auth       required     pam_sepermit.so

# Change to
auth       required     pam_yubico.so id=18752 key=bs8eO3Vas55uJN2dfis47KvS9vko= url=http://api.yubico.com/wsapi/2.0/verify?id=%d&otp=%s pam_sepermit.so

Save and exit

Note: If you are running your own validation server, the url to use will be different, remember to change it


Configuring SSH

The final step is to ensure SSH is configured the way we want it, for the yubikey route to be available, password based authentication must be enabled (consider it carefully before enabling - users without a yubikey file will not be able to login until a key has been associated, unless they already have a valid RSA keypair configured)

Start by checking the current config

egrep "UsePAM|PasswordAuthentication" /etc/ssh/sshd_config | grep -v "#"

If both are enabled, great, jump onto Testing (below), if not then you need to do the following

nano /etc/ssh/sshd_config

# Find the line
PasswordAuthentication no

# And change to
PasswordAuthentication yes

# Also ensure the following exists
UsePAM yes

# Save and exit, followed by
service sshd restart


Testing the Changes

Without exiting your existing SSH session (you'll need it to troubleshoot if something doesn't work), attempt to SSH to your server. It will likely log you in if you have a valid RSA keypair set up, so we'll pass SSH an invalid identity file (when asked for the key passphrase just hit enter)

ssh -i /dev/null $OURUSER@myserver

When prompted for the account password, enter the valid password followed by a short press on the Yubikey. You should be logged in

To make sure you haven't opened your system to brute-forcers, try SSH'ing with a valid password to an account without a yubikey configured, you shouldn't be allowed in.