2FA with the YubiKey & OpenBSD for SSH Access

By Calum MacRae

December 25, 2013

In this post, I'll be detailing the steps you can take to harden your remote SSH access, and achieve a two factor authentication setup with a YubiKey and OpenBSD's SSH server. https://i.imgur.com/6vEaZA6.jpg

The authentication principle

After carrying out the steps detailed here, you'll have an SSH server with which you can only establish a connection once the following authentication requirements have been met:

  1. Key pair passes with the presence of a permitted private key
  2. Passphrase for the key pair is correct
  3. Unique OTP provided by the YubiKey is correct

This isn't quite multi factor authentication (by definition), but it's damn good!

Who this is for

Well, for anyone looking for a hardened SSH server really. I use this setup on the firewall/router I built for remote SSH access to my home network (see I'm even confident enough to disclose that information).

Perhaps not as badass as port knocking, but it's a hell of a lot better than some other proposed security measures.

What we'll be using

This setup is for use with the OpenSSH server. I won't specifically state it's just for OpenBSD, but as this tutorial details the YubiKey's use with BSDAuth, and specifically OpenBSD's login.conf, that's what you'll need to be using to follow these steps exactly. It can certainly be achieved with PAM, and therefore used with a wide variety of UNIX derived systems. So if you're confident you can adapt these steps to fit your needs, by all means do so. Just pray you don't lock yourself out of anywhere ;)

A quick note

I wanted to state; this tutorial does not walk you through the install/setup of OpenBSD. If you're looking for information on how to do so, visit OpenBSD's official site…. plus, it takes like 3 minutes from start to finish, just dive in people!

The "layout"

It's important to understand the technologies we're using here and how they relate to one another.

Logging in with BSDAuth

Let's start with the last step of authenticaion. I know that seems a bit backwards but, you'll understand once this all starts to come together. So, you can set up your OpenBSD system to accept a OTP from the YubiKey as a means of authenticating a user's login. Think of this as completely disjointed from remote access right now, we're just talking about logging into the system on, say, your desktop. In fact, I use my YubiKey to log into my desktop running OpenBSD.

This replaces the usual process of typing a static password you have safely locked away in your memory. Instead of typing in the name of your cat's favourite day of the week followed by the hexadecimal value of the colour of your first car….. or some other equally obscure collection of (dare I say) memorable data, you simply touch that little pad on the YubkiKey, it authenticates using BSDAuth, and away you go!

BSDAuth's relation to SSH access

So, if you understand the above (granted I didn't go into grooling detail, that is yet to come), then perhaps you can understand the following notion: One can log into a remote system via SSH using simply the user's password on that system (if it has been set up that way). Taking this into consideration, hopefully it becomes clear that once this static password has been replaced with the OTP process… you could still SSH as that user, but use the YubiKey instead of the static password.

Key pair authentication

It's imperitive that you, dear reader, understand at least the basic concept of using key pair authentication with SSH. This is an important thing to understand as it's a key component to this setup…. no pun intended. Once we've set up our server for this kind of authentication, the first thing the server will look at when someone attempts to establish an SSH connection is the remote user's private key. If the private key provided by the remote user does not legitimately match with any public key listed in the authorized_keys file of the user on the destination host, the connection will be closed. This is, essentially, the remote part of our mental map for this setup. We want to ensure that, first, anyone attempting to access our system has a legitimate key pair.

Tying the two together

To summarize:

  • We must have a legitimate keypair to establish the initial connection with the SSH server
  • We must then provide a OTP using the YubiKey for login authentication with BSDAuth

In fact, we'll also be adding a passphrase onto the public key. This adds another layer of security, as the user of the key pair will have to authenticate the key pair itself with a passphrase.

Let's get started!

First, going back to the BSDAuth/local login; the means by which we use the YubiKey in conjunction with BSDAuth is a login module, called login_yubikey.

Here's a clear and concice explaination of how it works, taken from the login_yubikey manpage:

login_yubikey will read the user's UID (12 hex digits) from the file user.uid, the user's key (32 hex digits) from user.key, and the user's last-use counter from user.ctr in the /var/db/yubikey directory. If user does not have a UID or key, the login is rejected. If user does not have a last-use counter, a value of zero is used and any counter is accepted during the first login. The one-time password provided by the user is decrypted using the user's key. After the decryption, the checksum embedded in the one-time password is verified. If the checksum is not valid, the login is rejected. If the checksum is valid, the UID embedded in the one-time password is compared against the user's UID. If the UID does not match, the login is rejected. If the UID matches, the use counter embedded in the one-time password is compared to the last-use counter. If the counter is less than or equal to the last-use counter, the login is rejected. This indicates a replay attack. If the counter is larger than the last-use counter, the counter is stored as the new last-use counter, and the login is accepted.

So first let's get these files set up:

Getting your UID and key

In order to obtain your UID and key, you'll need to install the yubikey-personalization-gui package. This will let you generate a paired UID and key, then write it to the YubiKey for use with login_yubikey.

Once installed, run the application and select the first option at the top Yubico OTP, then select Quick. You'll be presented with a new screen. Under the Yubico OTP Parameters (auto generated) section, unselect the Hide values option. This will reveal the newly generated UID and key (this is auto generated upon each run of the application).

Using your UID and key with login_yubikey

Copy the Private Identity (6 bytes Hex) value into a file named after your user in: /var/db/yubikey/ For example, mine is as follows /var/db/yubikey/cmacrae.uid. Do the same for the key, copy the Secret Key (16 bytes Hex), paste it into a file like so: /var/db/yubikey/user.key (again, cmacrae.key in my case).

Ensure the permissions on these files is set correctly:

chown -R root:auth /var/db/yubikey/
chmod -R 0644 /var/db/yubikey/

Now that you have these values recorded in the appropriate locations, write them to Slot 1 on your key (or if you'd prefer to keep Yubico's default config, write to Slot 2, however; each time you use the key, you will have to hold the touch finger pad for 4 seconds). You can write this config to the key by selecting 'Write configuration' and selecting the desired slot. This will also prompt where to save a CSV file of the config (something I'd deem unecessary, and a security risk) so just save it to your $HOME and remove it later.

Setting up login.conf

Edit the /etc/login.conf file and add yubikey at the beginning of the auth-defaults entry, like so:

# Default allowed authentication styles

This takes care of the YubiKey part of our setup. You probably want to test this works as expected. If anything is unusual, retrace your steps. If you end up somehow locking yourself out of your system, you can boot to the ramdisk by entering bsd.rd at the bootloader. From here you can drop into a shell, mount your filesystems and edit /etc/login.conf back to use password authentication.

SSH key pair

If you're growing tired of reading; fear not. This part is nice 'n easy!

If you're following this tutorial, I'll assume a certain level of prior knowledge and take it you already know how to generte an SSH key pair. If you're not familiar with this, go read up on it! If you don't know, I'll take pitty on you: ssh-keygen …but still go and read up on it, there are better options than the defaults given to you when running this utility without any flags.

You can use any of the ciphers supported by OpenSSH for this (read more at https://openssh.com).

Make sure when you generate your key pair, you add a passphrase. This provides another layer of security!

And of course, once you have your keypair, you need to paste the public key into the ~/.ssh/authorized_keys file of the user you're going to be SSH'ing as.

Chaining authentication methods in sshd

Now, we can finally chain these authentication methods in the SSH daemon's configuration.

In the file /etc/ssh/ssd_config, add the following lines:

# Chained authentication
AuthenticationMethods publickey,password

This will tell the SSH server to first authenticate the key pair from the remote machine (also prompting for the passphrase you added to your public key…. you added one, right?), then ask for a password. This password of course will be the OTP provided by the YubiKey.

Try it out! You should see something like this:

$ ssh user@server
Authenticated with partial success.
user@server's password:

Note - If there is no passphrase prompt shown here, as in this example, this is because you have already unlocked your key pair with your passphrase using your desktop's keychain application for this session

So there you have it!

There are now, essentially, 3 points of authentication:

  • The server ensures a legitimate, permitted key pair is present on the remote machine
  • A correct passphrase has to be provided to unlock the key pair for authentication
  • The server prompts for the users password, which is now a unique OTP provided by the YubiKey

That's pretty nifty, right?

I should get to bed…

Well, it's been a good night of writing. I hope you've enjoyed this post, and taken something decent from it.

Until next time, happy hacking :)

Posted on:
December 25, 2013
9 minute read, 1763 words
security bsd networking
See Also:
"Cloud-like" Infrastructure at Home - Part 1: LoadBalancers on the Metal
Your own VPN with OpenIKED & OpenBSD