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).
Pre-Requisites
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
OURUSER="ben"
YUBIID='nnnnnnnnnnnn'
mkdir ~$OURUSER/.yubico
echo "$OURUSER:$YUBIID" > ~$OURUSER/.yubico/authorized_yubikeys
chmod 700 -R ~$OURUSER/.yubico
chown $OURUSER:$OURUSER ~$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.