This article contains tips & tricks for using YubiKeys for authentication.contents…
sudo
over SSH using YubiKey
Remembering root passwords for machines is annoying and error-prone. You can reuse the same passwords and be insecure. You can use different passwords and forget them. You can type them into IRC and then have to reset them. But there is a better way.
In modern Linux & Unix systems, Pluggable Authentication Modules (PAM) can provide multiple ways of authenticating a user. The most common one is “asking for a password”, but they can also query external network services or require a second factor. The module pam_ssh_agent_auth
authenticates users by checking against SSH keys from a connected SSH agent, which means that we can have passwordless sudo
when logged in remotely.
Using pam_ssh_agent_auth
with a YubiKey is both more convenient and more secure than passwords: you only need to tap the YubiKey, and because you need to tap the YubiKey, becoming root requires a physical action on your part.
NB: Technically this allows all SSH keys loaded into the SSH Agent to be used to become root. If you have a mixture of YubiKey keys and on-disk SSH keys, I would recommend using ssh-askpass
/ SSH_ASKPASS
to require confirmation.
Debian & Ubuntu
TL;DR:
- Install
pam_ssh_agent_auth
. - Enable
pam_ssh_agent_auth
for use with sudo
. - Allow
sudo
to maintain access to SSH_AUTH_SOCK
. - Connect to our remote machine with SSH agent forwarding and never have to remember a server password again.
On your remote machine, first install the SSH agent authentication PAM:
$ apt install libpam-ssh-agent-auth
Then, enable and configure the PAM module for use with sudo
:
$ cat /etc/pam.d/sudo
#%PAM-1.0
# Allow users to use their regular authorized SSH keys for sudo,
# and allow them to manage the keys themselves.
auth sufficient pam_ssh_agent_auth.so file=~/.ssh/authorized_keys allow_user_owned_authorized_keys_file
# # Alternatively, have a single central key file, owned by root.
# # This is useful if you only want a subset of SSH keys to grant root permissions.
# auth sufficient pam_ssh_agent_auth.so file=/etc/ssh/sudo_authorized_keys
@include common-auth
@include common-account
@include common-session-noninteractive
Allow sudo
to maintain access to the SSH agent by keeping SSH_AUTH_SOCK
:
$ cat /etc/sudoers
Defaults env_keep += SSH_AUTH_SOCK
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# User privilege specification
root ALL=(ALL:ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
To test it, connect to the machine with ssh -A server.example.com
, and try using sudo
: it should not ask for a password, and the YubiKey should flash for a tap.
For convenience, add ForwardAgent yes
to the relevant hosts your SSH config to set -A
by default:
$ cat ~/.ssh/config
Host server.example.com
ForwardAgent yes
Host 192.168.16.*
ForwardAgent yes
NixOS
On NixOS, the configuration for the server is much simpler:
$ cat /etc/nixos/configuration.nix
{ config, pkgs, ... }:
{
. . .
security.pam.enableSSHAgentAuth = true;
security.pam.services.sudo.sshAgentAuth = true;
users.users.eth.openssh.authorizedKeys.keys = [
"ssh-rsa . . .",
"ssh-rsa . . .",
];
}
To test it, connect to the machine with ssh -A server.example.com
, and try using sudo
: it should not ask for a password, and the YubiKey should flash for a tap.
For convenience, add ForwardAgent yes
to the relevant hosts your SSH config to set -A
by default:
$ cat ~/.ssh/config
Host server.example.com
ForwardAgent yes
Host 192.168.16.*
ForwardAgent yes