Weisser Zwerg Logo

Weisser Zwerg

Step Up Your SSH Game: A Deep Dive into FIDO2 Hardware Keys and ProxyJump Configuration

Published by Weisser Zwerg Blog on

How to configure OpenSSH to use a FIDO2 hardware key with ProxyJump.

Rationale

Recently, I stumbled upon an exciting discovery that I’m eager to share with you. Did you know that you can use any FIDO2 hardware key, like a Yubikey, Nitrokey, Solokey, or Trezor, etc., as a hardware OpenSSH key? This setup eliminates the need to store private keys on your devices, significantly reducing the attack surface. While there are other ways to achieve this, such as teleport or similar, the FIDO2 setup is a drop-in replacement for your current keys and requires no additional infrastructure.

Create the OpenSSH key on the FIDO2 hardware key.

Creating an OpenSSH key on a FIDO2 hardware key is a straightforward process. In this post, I’ll show you how to do it using a Nitrokey and the nitropy command line interface. I tested the procedure with a Yubikey, and it worked just as well. While the Yubico ykman CLI tool is picky and only works with Yubikeys, the nitropy CLI tool is more flexible and works with other keys too.

To create the key, simply execute the following commands:

export IDENTITY="$HOME/.ssh/fido2-nitrokey.ed25519-sk"
ssh-keygen -t ed25519-sk -f ${IDENTITY} -O resident -O verify-required -O application=ssh:nitrokey
pipx install --suffix=-git git+https://github.com/Nitrokey/pynitrokey.git
nitropy-git fido2 list-credentials

When you create the OpenSSH key, it will ask you for a PIN (which may be referred to as a “password”). It will also ask you for a password to encrypt the private key on disk. However, I don’t think this password is necessary since the PIN already protects the hardware key. I therefore left it empty. Note that the private key is not really a key, but rather a “pointer” to the hardware key. You can recreate the file from the hardware key if you lose it (see below).

Here are the important options to keep in mind when using ssh-keygen:

  • -t ed25519-sk or -t ecdsa-sk: the -sk makes sure that the security key is used
  • -f ${IDENTITY}: this is where the private and public keys are written to. The file name given is the name of the private key. The public key is the same path with a .pub appended. As mentioned earlier, the private key is not really a key, but rather a “pointer” to the hardware key.
  • -O resident: use this flag to write the key into a discoverable slot of the hardware key. Check out this link to learn more about the difference between discoverable and non-discoverable credentials.
  • -O verify-required: this flag requires you to unlock the key via a PIN when you try to use it.
  • -O no-touch-required: you can pass this flag to ssh-keygen to tell it not to require touching the device every time. However, I was not able to make this work with either the Nitrokey or the Yubikey.
  • -O application=ssh:YourTextHere: this flag is optional, but it may make it easier to identify the hardware key, especially if you have several hardware keys.

If you take the hardware key to another machine, you can use the following command to create the private key file in the current directory:

ssh-keygen -K

You would then have to move it in your ~/.ssh/ directory.

Now that you have created the key, you can copy the public key to your target machine where you want to ssh to. For example, I used my Odroid M1 for this test:

ssh-copy-id -i ${IDENTITY}.pub odroid@odroid

You should now be able to test that your key setup works by:

ssh -v -o "IdentitiesOnly=yes" -i ${IDENTITY} odroid@odroid

If you followed the steps outlined above, you will first have to enter the PIN and then touch the key to prove your presence.

Configure ProxyJump

To make the following work, you need two machines and ensure that the public key is also present on the second machine. I use my x99 machine for this purpose.

ssh-copy-id -i ${IDENTITY}.pub cs@x99

To set up the connection to the first hop, add the configuration below to ~/.ssh/config:

Host cttest1nitro
  # ForwardAgent true
  IdentitiesOnly       yes
  HostName             odroid
  User                 odroid
  IdentityFile         ~/.ssh/fido2-nitrokey.ed25519-sk
  Port                 22
  ControlMaster        auto
  ControlPath          ~/.ssh/odroid.nitro.sock
  ControlPersist       60s
  ServerAliveInterval  0

Next, use the first hop to make the connection to the second hop by adding the following configuration:

Host cttest2nitro
  HostName             x99
  User                 cs
  IdentityFile         ~/.ssh/fido2-nitrokey.ed25519-sk
  Port                 22
  ControlMaster        auto
  ControlPath          ~/.ssh/x99.nitro.sock
  ControlPersist       60s
  ServerAliveInterval  0

  ## sample for ProxyJump
  ProxyJump cttest1nitro

You should now be able to ProxyJump directly to the second hop machine:

ssh cttest2nitro

This will require you to enter the pin followed by touching the key twice, because you effectivly SSH into two machines in sequence.

While the following part is not strictly necessary:

  ControlMaster        auto
  ControlPath          ~/.ssh/odroid.nitro.sock
  ControlPersist       60s
  ServerAliveInterval  0

it saves you from entering the pin and touching the hardware key for every SSH command you issue. The above section, turns on SSH connection multiplexing, and the connection stays alive for at least 60 seconds. This feature is especially useful when you run a script that issues several SSH commands in sequence.

If you do not want to wait for the timeout, then you can execute ssh -O exit cttest1nitro to close the multiplexed open SSH connection and its associated socket.

Configure sshd on the Target Machine

To make your target machine more secure, you should turn off password authentication and require the entry of the pin of keys. To do that, you would add the following to your /etc/ssh/sshd_config on the target machine:

PasswordAuthentication no
ChallengeResponseAuthentication no

PubkeyAuthOptions verify-required

Finally, you would issue a restart of the sshd daemon.

systemctl restart ssh

SSH Agent

You do not need to use the ssh agent, but if you do want to use it, you can do that by:

killall ssh-agent
eval $(ssh-agent)
ssh-add -K
ssh-add -L

In principle, it should not be necessary to kill the agent first, but for whatever reason, without killing the agent first, I sometimes had trouble adding the key to the agent, and it exited with an error.

References

Additonal Remarks:

In my experience, the Trezor stands out as the best FIDO2 device. It offers two key features that make it my preferred choice:

  • Firstly, you can create a backup of your keys. This is a crucial advantage because it eliminates the need for a second hardware key to access your target machines in case you lose your main hardware key. With a backup stored in a secure location, you can rest assured that you will be able to restore the keys.
  • Secondly, the Trezor has a touchscreen that allows you to enter your PIN directly on the device. This is a significant security advantage over other hardware keys that require you to type your PIN on the machine where you use the key. This could potentially compromise your security if someone installed a keylogger or similar software.

While some FIDO2 hardware key manufacturers tout the fact that their keys cannot be backed up (are not copyable) as an advantage, I personally find it to be a disadvantage. The need for double key management is eliminated with the ability to create a backup.

In theory, mobile devices that support platform-created FIDO2 passkeys that are copyable could be another good option for SSH keys. However, without additional hardware like the IDmelon Reader, this is not currently possible out of the box. I’ve posed the question, Can I use an iPhone connected via USB to a computer as a FIDO2 security key (for example in OpenSSH)? to see if anyone has found a workaround.

Conclusion

In conclusion, using FIDO2 hardware keys as OpenSSH keys is an excellent way to enhance your security. Additionally, it doesn’t require any additional infrastructure, making it an easy and cost-effective solution. So, if you’re looking for a way to enhance your security, consider using FIDO2 hardware keys as OpenSSH keys.

Feedback

Have you written a response to this? Let me know the URL via telegraph.

No mentions yet.