Enabling Yubikey for SSH 2FA

Enabling Yubikey for SSH 2FA

In the past I wrote about setting up a bastion hosts and why they are important. I thought I’d take the time to explain how to utilize a Yubikey as a mechanism to perform 2FA when you SSH into bastion hosts.

There are a few key components here:

  1. Buying a Yubikey
  2. Enabling PAM authentication in SSH
  3. Installing the Yubikey PAM module
  4. Getting a Yubico API Key
  5. Setting up authorized Yubikeys.
  6. Configuring PAM to use Yubikey for 2FA
  7. Testing it out

Buying a Yubikey

Yubico sells a number of different Yubikeys for specific purposes. A the time of writing, the Yubikey 5 is the flagship device and is perfect for general 2FA. Yubico usually ship within 2 days and their customer service has been great to me in the past.

Enable PAM authentication in SSH

You will need to configure /etc/ssh/sshd_config to have the following parameters

PubkeyAuthentication yes
PasswordAuthentication no
UsePAM yes
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive:pam

Installing the Yubikey PAM module

If you’re on EPEL/ RHEL/ CentOS, you can install it via yum

sudo yum install pam_yubico

Otherwise if you’re on a Debian distribution:

sudo add-apt-repository ppa:yubico/stable
sudo apt-get update
sudo apt-get install libpam-yubico

Getting a Yubico API Key

In order to use the PAM module, assuming you’re not running your own Yubico validation servers, you’ll need to register for an API key at: https://upgrade.yubico.com/getapikey/. Simply provide an email address and press your Yubikey and you’ll get an id and a key (which ends with an =).

Setting up authorized Yubikeys.

The Pubico PAM module allows you to configure Yubikey the authorized Yubikeys in one of two ways:

  1. A file in the users home directory ~/.yubico/authorized_yubikeys. This file is formatted in the following manner:
<username>:<Token-ID-1>:<Token-ID-2>:<Token-ID-n>

So it looks something like this:

michael:ccccccrjzigk:ccccccirfkl
  1. A file in a central location (e.g. /etc/yubikeys). This file follows the same format, however one user-name per line:
michael:ccccccrjzigk:ccccccirfkl
bob:ccccccirkdkx

The way to get the token ID is to press your Yubikey in a text editor and copy the first 12 characters of the string that is produced. I usually do this in Python just to be sure:

michael@laptop~ % python
>>> a = "eibeeliibcjkcljuiieijhcckeerejbikvhhcbchkgin"
>>> b = a[0:12]
>>> b
'eibeeliibcjk'
>>> len(b)
12

There is no security advantage between methods, but depending on if and how you’re using configuration management, there may be a preferred method here. You can find more information at the Yubico site.

Configuring PAM to use Yubikey for 2FA

In /etc/pam.d/sshd: on the top line, add the following string, replacing the id and key from the previous step.

  • If you’re using option 1
auth  required  pam_yubico.so id=<id> key=<key> debug
  • If you’re using option 2
auth  required  pam_yubico.so id=<id> key=<key> debug authfile=/path/to/mapping/file

You will need to restart sshd to pick up these changes.

Testing it out

Note: If you’re using pihole, make sure that the api*.yubico.com is not being blocked.

We recommend that you keep the terminal you’re using to configure your bastion host open and then try and SSH to the bastion in a new tab/ window. When you SSH, you should be prompted for your Yubikey:

michael@laptop ~ % ssh bastion
YubiKey for `michael`:
Last Login: Thu June 10 20:22:53 2020 from 192.168.x.x
[michael@bastion ~]$

Credit to Yubico for the cover image

Last modified: 3 July 2020