Note: for the whole article, I will work with a linux user called ansible on a host called also…ansible! 🙂

ssh-keygen

When you use ssh-keygen you will generate a private and public key pair. And you’ll have to choose which algorithm to use.

At the time of writing this article, an RSA key with 4096 bits is the best quality/compatibility ratio but you can begin to use ED25519 on recents OS.

There is also DSA with 4096 bits, but it’s the almost the same security level as RSA and it’s much more slower during the signature verification.

[ansible@ansible ~]$ ssh-keygen -f ~/.ssh/mykey -t rsa -b 4096
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ansible/.ssh/mykey.
Your public key has been saved in /home/ansible/.ssh/mykey.pub.
The key fingerprint is:
SHA256:gDs0Rvy78IdSfKIWnmSuMu3cKD36yK+LtvmPXXpt7J0 ansible@ansible
The key's randomart image is:
+---[RSA 4096]----+
|   ..            |
|   ...           |
|    =..          |
|   o o..         |
|    o. .S        |
|    =.= .        |
| o = B *o        |
|*+=oX *..+. .    |
|=&%Bo=..o. E     |
+----[SHA256]-----+
[ansible@ansible ~]$ ls ~/.ssh/mykey
mykey      mykey.pub

It ask you to enter a passphrase but it’s not mandatory, you can let it empty. We will see later more about the passphrase.

mykey.pub is the public key.

Authorized your key on target hosts

Once an SSH key has been created, the ssh-copy-id command can be used to install the public key as an authorized key on the server. Once the key has been authorized for SSH, it grants access to the server without a password.

For example use the following command to authorized your SSH key for the user user1 in the target host1:

ssh-copy-id -i ~/.ssh/mykey user1@host1
# or
ssh-copy-id -i ~/.ssh/mykey.pub user1@host1

Important: whether you specificy the private key or the public key as parameter to ssh-copy-id it will only copy the public key to the target host

Or you can also do it manually:

on the target user1@host1 (user1 on host1), just drop your key on host1 and add it as an authorized key to user1:

cat mykey.pub >> /home/user1/.ssh/authorized_keys

Important: if you’ve just created authorized_keys file, ensure its permissions are 600. Otherwise for security reasons it can cause problems when you ssh from another host.

Furthermore, ensure .ssh directory containing authorized_keys is at maximum 755, otherwise if 775 the ssh command to this user will fail.

How to use your private key from another host?

You just have to copy the private key on the host you want, and you have to put the following permissions for security reasons (otherwise you’ll have an error when trying to connect). Of course you don’t want the key to be readable by other users than the one where you’ve copied it. Imagine you have copied it in some path, then put the permissions 0600 on the key, and use it like this to connect to user1 on host1:

chmod 0600 path/mykey
ssh -i path/mykey user1@host1

How to debug ssh connections?

If you have ssh connection errors, go to the target host, the one on which you want to connect without password and then:

vim /etc/ssh/sshd_config

At look for LogLevel you shoud find a line #LogLevel INFO, uncomment it and replace it by:

LogLevel DEBUG

Then reload the service sshd:

service sshd reload

Depending on your distro, you’ll find logs inside:

vim /var/log/secure

or

vim /var/log/auth.log

Passphrase for more security and ssh agent for keeping it easy to use

This not mandatory but you can use a passphrase in order to encrypt your private key. Then even if your private key is leaked, it is not compromised.

“More than 90% of all SSH keys in most large enterprises are without a passphrase. However, this depends on the organization and its security policies.”

https://www.ssh.com/academy/ssh/passphrase

ssh agent will help you not to enter it each time, it’s like a vault

To see if there is a running ssh agent on your distro:

[ansible@ansible ansible]$ set | grep SSH_AUTH_SOCK
[ansible@ansible ansible]$

if there is no output, you have to start an ssh agent:

[ansible@ansible ansible]$ eval $(ssh-agent)
Agent pid 28970
[ansible@ansible ansible]$ set | grep SSH_AUTH_SOCK
SSH_AUTH_SOCK=/tmp/ssh-mficIutpYt8g/agent.28969

Here a process with ID 28970 has been created, it’s the ssh-agent.

A ssh agent by default is a process that won’t expire, if you close your session the ssh agent process is still alive and active.

By default when you add a ssh key with ssh-add command it has un unlimited timeout, but you can also specify a lifetime to the ssh-add command with the -t option. Otherwise anybodyelse that will reach access this ssh-agent will be able to exploit the key previously added.

if you execute ssh-agent without eval, you have this output:

[ansible@ansible ~]$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-9a7b5mcqOHyB/agent.29094; export SSH_AUTH_SOCK;
SSH_AGENT_PID=29095; export SSH_AGENT_PID;
echo Agent pid 29095;

And then if you verified the existence of the ssh-agent:

[ansible@ansible ~]$ set | grep SSH_AUTH_SOCK
[ansible@ansible ~]$
[ansible@ansible ~]$ ps -ef | grep 29095
ansible    29095       1  0 21:43 ?        00:00:00 ssh-agent
ansible    29212   29333  0 21:59 pts/0    00:00:00 grep --color=auto 29095
[ansible@ansible ~]$

It’s not shown but it exists, there is a ssh agent process with the id 29095.

The agent daemon has been created but you can’t still use it, you have to execute the commands that are listed in the output:

[ansible@ansible ~]$ SSH_AUTH_SOCK=/tmp/ssh-9a7b5mcqOHyB/agent.29094; export SSH_AUTH_SOCK;
[ansible@ansible ~]$ SSH_AGENT_PID=29095; export SSH_AGENT_PID;
[ansible@ansible ~]$ set | grep SSH_AUTH_SOCK
SSH_AUTH_SOCK=/tmp/ssh-9a7b5mcqOHyB/agent.29094
[ansible@ansible ~]$

Then you can understand you can also use this agent in another terminal connected to this same host (other sessions), you just have to copy paste the commands.

once your agent is started you need to add the passphrase to the agent:

[ansible@ansible ansible]$ ssh-add -t 3600 ~/.ssh/mykey
Enter passphrase for /home/ansible/.ssh/mykey:
Identity added: /home/ansible/.ssh/mykey (ansible@ansible)
Lifetime set to 3600 seconds
[ansible@ansible ansible]$

Securing the use of the ssh-agent with a timeout and a kill of the process when you exit your session

Add a timeout to your ssh-add key and also just kill the process when you exit the session:

# ~/.bash_logout

if [ ! -z "$SSH_AGENT_PID" ]; then
        kill $SSH_AGENT_PID
fi

Is it possible to change the passphrase when I have already deployed my public keys (ssh-copy-id)?

Yes. A passphrase is only use to encrypt the private key, it doesn’t affect the public key.

[ansible@ansible ansible]$ ssh-keygen -p -f ~/.ssh/mykey

It will ask you the original passphrase and then you’ll have to enter the new passphrase.