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: Buying a Yubikey Enabling PAM authentication in SSH Installing the Yubikey PAM module Getting a Yubico API Key Setting up authorized Yubikeys. Configuring PAM to use Yubikey for 2FA 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: 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 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
I was at a meetup the other night and a student mentioned that they were learning about bastion hosts and wanted to learn more. So I thought I would do a deep dive on what they are and why to use them. What Bastion hosts are instances that sit within your public subnet and are typically accessed using SSH or RDP. Once remote connectivity has been established with the bastion host, it then acts as a ‘jump’ server, allowing you to use SSH or RDP to log in to other instances. https://cloudacademy.com/blog/aws-bastion-host-nat-instances-vpc-peering-security/ Why Bastion hosts act as a gateway or ‘jump’ host into a secure network. The servers in the secure network will ONLY accept SSH connections from bastion hosts. This helps limit the number of points where you can SSH into servers from and limit it to a trusted set of hosts. This also significantly helps auditing of SSH connections in the secure network. Bastion hosts typically have more strigent security postures. This includes more regular patching, more detailed logging and auditing. How Bastion setups are rather quiet simple, here are a few simple steps to set one up: Provision a new server(s) that are ONLY dedicated for the purpose of bastion access Install any additional security measures (see the cyberciti reference below for specific recommendations Ensure that all servers in the secure network ONLY accept SSH connections from the bastion server(s) Configure your SSH client to talk to hosts in your private network. Replace the IdentityFile and domain-names to suit your network: $ cat ~/.ssh/config Host *.secure.example.com IdentityFile %d/.ssh/keyname.extension ProxyCommand ssh bastion.corp.example.com -W %h:%p Host bastion.corp.example.com IdentityFile %d/.ssh/keyname.extension Host * PubkeyAuthentication yes References https://www.cyberciti.biz/faq/linux-bastion-host/ https://cloudacademy.com/blog/aws-bastion-host-nat-instances-vpc-peering-security/ https://www.sans.org/reading-room/whitepapers/basics/hardening-bastion-hosts-420 https://blog.scottlowe.org/2017/05/26/bastion-hosts-custom-ssh-configs/