SSH Key Generation & SSH Agent Configuration: A Quick Reference For Secure Remote Access
Note: This article is not intended to be a comprehensive guide on the topic. For detailed information and a comprehensive guide on SSH, I highly recommend referring to the excellent article by DigitalOcean: 'SSH Essentials: Working with SSH Servers, Clients, and Keys'. Their guide covers the important aspects of SSH in great detail including server configuration.
Generating SSH Keys
See the ssh-keygen manual for more information regarding the flags used below:
RSA (Rivest-Shamir-Adleman) based Key Generation
#!/usr/bin/env bash
ssh-keygen \
-t rsa \
-a "<Number of KDF (key derivation function) rounds used>" \
-b "<Number of bits in the key>" \
-C "<Some comment such as your email address>" \
-N "<Passphrase used for encrypting your private key>" \
-f "</path/to/private-key>"
For example:
#!/usr/bin/env bash
ssh-keygen \
-t rsa \
-a 128 \
-b 4096 \
-C "user@example.com" \
-N "hopefully-a-very-strong-passphrase" \
-f "~/.ssh/example-server-1"
ECDSA (Elliptic Curve Digital Signature Algorithm) based Key generation
#!/usr/bin/env bash
ssh-keygen \
-t ed25519 \
-a "Number of KDF (key derivation function) rounds used" \
-C "Some comment such as your email address>" \
-N "<Passphrase used for encrypting your private key>" \
-f "</path/to/private-key>"
For example:
#!/usr/bin/env bash
ssh-keygen \
-t ed25519 \
-a 128 \
-C "user@example.com" \
-N "hopefully-a-very-strong-passphrase" \
-f "~/.ssh/example-server-1"
Note: The -b bits
option is omitted for ed25519
based key generation. As per the ssh-keygen documentation
For ECDSA keys, the -b flag determines the key length byselecting from one of three elliptic curve sizes: 256, 384 or 521 bits. Attempting to use bit lengths other than these three values for ECDSA keys will fail. ECDSA-SK, Ed25519 and Ed25519-SK keys have a fixed length and the -b flag will be ignored.
Managing Multiple SSH Key-Pairs
If you protect all of your private keys with passphrases and assuming that your servers only allow key-based access, then you would need the following information to connect to your server:
- Username
- Server hostname/IP
- Private key
- Private Key Passphrase
Keeping track of what username, hostname, private key, and passphrase to use can easily get out of hand when different keys for different systems are used.
SSH Configuration
Instead, the hostname, username, and related private key can be configured under:
~/.ssh/config
(User Level)/etc/ssh/ssh_config
(System Level)
See ssh_config documentation for more information.
Host <Host>
HostName <hostname/ip>
User <username>
IdentityFile </path/to/private-key>
Port <port, default: 22>
Typically, you'd run something similar to the following to connect to a server via SSH:
#!/usr/bin/env bash
ssh username@hostname -i ~/keys/your-private-key
# For example
ssh admin@example.com -i ~/.ssh/custom/example-key
We can define a host configuration under ~/.ssh/config
as follows:
Host example
HostName example.com
User admin
IdentityFile ~/.ssh/custom/example-key
Port 22
This allows us to ssh to example.com
as the admin
user without having to specify either the username or hostname by referencing the Host
as follows:
#!/usr/bin/env bash
ssh example
However, we'll still be prompted for our private key passphrase.
ssh-agent
An ssh-agent
can be configured in addition to ssh configuration to avoid manually providing passphrases over and over again. As per the ssh-agent documentation:
ssh-agent is a program to hold private keys used for public key authentication. Through use of environment variables the agent can be located and automatically used for authentication when logging in to other machines using ssh
In other words, the ssh-agent
is a utility program that runs in the background and solves the problem of repeatedly entering private key passphrases.
However, an ssh-agent
on its own is scoped to a single session. This means that if you start a new session, you'll have to re-enter all of your passphrases.
Instead of just using the ssh-agent
on its own, we can use Funtoo Keychain to make things easier.
Funtoo Keychain for managing ssh-agent
According to the project wiki:
Keychain helps you to manage SSH and GPG keys in a convenient and secure manner. It acts as a frontend to ssh-agent and ssh-add, but allows you to easily have one long running ssh-agent process per system, rather than the norm of one ssh-agent per login session.
Installing & Configuring Funtoo keychain
- Install keychain:
#!/usr/bin/env bash
sudo apt install keychain
- Configure
keychain
in~/.bashrc
to automatically start up and prompt for private key passphrases. According to the keychain documentation:
Typically, private key files are specified by filename only, without path, although it is possible to specify an absolute or relative path to the private key file as well. If just a private key filename is used, which is typical usage, keychain will look for the specified private key files in ~/.ssh, ~/.ssh2, or with the -c/--confhost option, inspect the ~/.ssh/config file and use the IdentityFile option to determine the location of the private key. Private keys can be symlinks to the actual private key.
- As such, add the following command to your
~/.bashrc
to start keychain:
#!/usr/bin/env bash
eval `keychain --eval <your-private-key-1-in-~/.ssh> </full/path/to/your/private-key-2> ...`
# For Example:
# Suppose my ~/.ssh folder has the private key 'example' and that
# a key called 'external' is present in my opt directory.
eval `keychain --eval example /opt/external`
- If you start a new session or
source ~/.bashrc
, you'll be prompted to provide the passphrases for the private keys you specified. After you provide the passphrases the first time, you won't be prompted again until you either restart the system or explicitly clear the keys usingkeychain --clear
Troubleshooting
Fixing permissions for SSH
The following table can be used as a quick reference to fix any permission-related issues for SSH key files and configuration:
Folder / File | Permissions | Command |
---|---|---|
~/.ssh | Read, Write and Execute for the User only. | chmod 700 ~/.ssh |
~/.ssh/authorized_keys | Read and Write for the User only. | chmod 600 ~/.ssh/authorized_keys |
~/.ssh/config | Read and Write for the User only. | chmod 600 ~/.ssh/config |
Any private key | Read and Write for the User only. | chmod 600 ~/.ssh/<private-key> |
Any public key | Readable by all but writable only by the User. | chmod 644 ~/.ssh/<private-key> |
References / Additional Reading
- "Funtoo Keychain", funtoo, https://www.funtoo.org/Funtoo:Keychain
- "Funtoo Keychain Latest Documentation",
funtoo, https://github.com/funtoo/keychain/blob/master/keychain.txt - "How can I run ssh-add automatically without a password prompt", UNIX Stack
Exchange, https://unix.stackexchange.com/questions/90853/how-can-i-run-ssh-add-automatically-without-a-password-prompt - "How many kdf rounds for an ssh key", Crypto Stack Exchange, https://crypto.stackexchange.com/questions/40311/how-many-kdf-rounds-for-an-ssh-key
- "Permissions on private key in ssh folder", superuser.com, https://superuser.com/questions/215504/permissions-on-private-key-in-ssh-folder
- "Safe Curves", safecurves.cr.yp.to, https://safecurves.cr.yp.to/
- "ssh(1) — Linux manual page", https://man7.org/linux/man-pages/man1/ssh.1.html
- "ssh-add(1) — Linux manual page", https://man7.org/linux/man-pages/man1/ssh-add.1.html
- "ssh-agent(1): authentication agent - Linux man page",https://man7.org/linux/man-pages/man1/ssh-agent.1.html
- "ssh_config(5) — Linux manual page", https://man7.org/linux/man-pages/man5/ssh_config.5.html
- "ssh-keygen(1) — Linux manual page", Linux Manual Page, https://man7.org/linux/man-pages/man1/ssh-keygen.1.html
- "SSH Essentials: Working with SSH Servers, Clients, and Keys.", DigitalOcean (Ellingwood, Justin.), https://www.digitalocean.com/community/tutorials/ssh-essentials-working-with-ssh-servers-clients-and-keys.
- “What Is SSH-Keygen & How to Use It to Generate a New Ssh Key?”, SSH Communications Security, https://www.ssh.com/academy/ssh/keygen
- “Working with SSH Key Passphrases.”, GitHub, https://docs.github.com/en/authentication/connecting-to-github-with-ssh/working-with-ssh-key-passphrases.