docs/ssh.md

173 lines
6.0 KiB
Markdown
Raw Normal View History

2023-08-04 21:59:58 +00:00
---
title: Secure Shell
---
# SSH
There are a number of different methods for using SSH with a yubikey. Most
of them however require either proprietary components, or modifications to
servers. Such methods are broken and should not be promoted.
Here we will cover only methods that use standard tools, standard protocols,
and don't allow secret keys to come in contact with system memoy.
Secondly solutions here do not require any server modifications. This is key
because you will not be able to modify all systems you use that provide ssh
interfaces such as Github ssh push.
## PKCS11
With this interface it is possible to generate an ssh private key in a
particular format that can be stored inside a PKCS11 capable device such
as a Yubikey 5.
While this does not offer nearly as many assurances as the GPG setup detailed
below, it is the simplest to setup.
Note: Due to limitations in the PKCS11 spec, it is not possible to generate
keys stronger than 2048 bit RSA with this method. Consider the security
requirements of your organization before using this method.
### Generation
For a set of manual steps on how to set this up see:
[https://developers.yubico.com/PIV/Guides/SSH_with_PIV_and_PKCS11.html]
To simplify this process consider the following script:
[https://gist.github.com/lrvick/9e9c4641fab07f0b8dde6419f968559f]
### Usage
Since SSH will by default only scan folders such as ~/.ssh/ for keys
you will need to inform it that you wish it to also check for smartcards via
the OpenSC interface.
Before using ssh commands be sure you have started your ssh agent like so:
```
ssh-add -s $OPENSC_LIBS/opensc-pkcs11.so
```
## GPG
### Configure SSH to use your Security Token
This assumes you already have a Security Token configured with a GPG Authentication subkey.
The end result will be that you distribute the SSH Public Key from your Security Token to all VCS systems and servers you normally connect to via SSH. From there you will need to have your key insert it, and tap it once for every connection. You will also be required to tap the key for all SSH Agent forwarding hops removing many of the security issues with traditional ssh agent forwarding on shared systems.
#### Most Linux Distros
If you are using a recent systemd based distribution then all the heavy lifting
is likely already done for you.
We recommend simply adding the following to "/home/$USER/.pam_environment":
```
SSH_AGENT_PID DEFAULT=
SSH_AUTH_SOCK DEFAULT="${XDG_RUNTIME_DIR}/gnupg/S.gpg-agent.ssh"
```
#### Mac OS, WSL, Non-Systemd Linux Distros
```
echo >~/.gnupg/gpg-agent.conf <<HERE
enable-ssh-support
keep-display # Avoid issues when not using graphical login managers
HERE
```
Additionally if you are using OSX you will want to set a custom program for pin entry:
```
echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
```
Edit your ~/.bash_profile (or similar) and add the following lines to use gpg-agent (and thus the Security Token) as your SSH key daemon:
```
# If connected locally
if [ -z "$SSH_TTY" ]; then
# setup local gpg-agent with ssh support and save env to fixed location
# so it can be easily picked up and re-used for multiple terminals
envfile="$HOME/.gnupg/gpg-agent.env"
if [[ ! -e "$envfile" ]] || ( \
# deal with changed socket path in gnupg 2.1.13
[[ ! -e "$HOME/.gnupg/S.gpg-agent" ]] && \
[[ ! -e "/var/run/user/$(id -u)/gnupg/S.gpg-agent" ]]
);
then
killall gpg-agent
# This isn't strictly required but helps prevents issues when trying to
# mount a socket in the /run tmpfs into a Docker container, and puts
# the socket in a consistent location under GNUPGHOME
rm -r /run/user/`id -u`/gnupg
touch /run/user/`id -u`/gnupg
gpg-agent --daemon --enable-ssh-support > $envfile
fi
# Get latest gpg-agent socket location and expose for use by SSH
eval "$(cat "$envfile")" && export SSH_AUTH_SOCK
# Wake up smartcard to avoid races
gpg --card-status > /dev/null 2>&1
fi
# If running remote via SSH
if [ ! -z "$SSH_TTY" ]; then
# Copy gpg-socket forwarded from ssh to default location
# This allows local gpg to be used on the remote system transparently.
# Strongly discouraged unless GPG managed with a touch-activated GPG
# smartcard such as a Yubikey 4.
# Also assumes local .ssh/config contains host block similar to:
# Host someserver.com
# ForwardAgent yes
# StreamLocalBindUnlink yes
# RemoteForward /home/user/.gnupg/S.gpg-agent.ssh /home/user/.gnupg/S.gpg-agent
if [ -e $HOME/.gnupg/S.gpg-agent.ssh ]; then
mv $HOME/.gnupg/S.gpg-agent{.ssh,}
elif [ -e "/var/run/user/$(id -u)/gnupg/S.gpg-agent" ]; then
mv /var/run/user/$(id -u)/gnupg/S.gpg-agent{.ssh,}
fi
# Ensure existing sessions like screen/tmux get latest ssh auth socket
# Use fixed location updated on connect so in-memory location always works
if [ ! -z "$SSH_AUTH_SOCK" -a \
"$SSH_AUTH_SOCK" != "$HOME/.ssh/agent_sock" ];
then
unlink "$HOME/.ssh/agent_sock" 2>/dev/null
ln -s "$SSH_AUTH_SOCK" "$HOME/.ssh/agent_sock"
fi
export SSH_AUTH_SOCK="$HOME/.ssh/agent_sock"
fi
```
Now switch to using this new setup immediately:
```
$ killall gpg-agent
$ source ~/.bash_profile
```
### Get SSH Public Key
You (or anyone that has your GPG public key) can get your SSH key as follows:
```
$ gpg --export-ssh-key you@email.com
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcjW34jewR+Sgsp1Kn4IVnkb7kxwZCi2gnqMTzSnCg5vABTbG
jFvcjvj1hgD3CbEiuaDkDqCuXnYPJ9MDojwZre/ae0UW/Apy2vAG8gxo8kkXn9fgzJezlW8xjV49sx6AgS6BvOD
iuBjT0rYN3EPQoNvkuqQmukgu+R1naNj4wejHzBRKOSIBqrYHfP6fkYmfpmnPyvgxbyrwmss2KhwwAvYgryx7eH
HRkZtBi0Zb9/KRshvQ89nuXik50sGW6wWZm+6m3v6HNctbOI4TAE4xlJW7alGnNugt3ArQR4ic3BeIuOH2c/il4
4BGwdRIp7XlSkkf8cZX59l9kYLaDzw4Z cardno:000603703024
```
You can paste that into your list of authorized keys on all VCS and systems you have access to.
You should disable any other keys that are not backed by a Security Token.