The ssh-keygen utility is used for ssh key generation. This post will walk you through how to generate a new ssh key, configure its use, and use it for authentication against the hosts or systems you need to authenticate to. At the end we will walk through how to test ssh key and password authentication against an openssh docker container.
What is SSH?
SSH is a protocol which primarily uses public key cryptography, or asymmetric cryptography although it also supports passwords. Asymmetric keys consist of a public and private key, which we will create in the next section. The SSH protocol consists of a client and server and is a method for securely authenticating a client to a remote server. The SSH protocol is a competitor of other authentication protocols such as telnet and rologin, and even better an upgrade from FTP which is insecure. Secure FTP is FTP with SSH protection, making it a secure method of transferring files.
SSH provides a strong cryptographic authentication method for securely accessing a remote server.
The SSH protocol specification and standard consists of four different RFCs.
- The Secure Shell (SSH) Protocol Architecture – RFC 4251
- The Secure Shell (SSH) Authentication Protocol – RFC 4252
- The Secure Shell (SSH) Transport Layer Protocol – RFC 4253
- The Secure Shell (SSH) Connection Protocol – RFC 4254
There is an additional RFC documenting the standard for the public key file format for SSH keys. This is RFC 4716.
SSH is commonly used for the following purposes:
- Secure authentication from a client to a server
- File transfers
- Remote commands
In a later section, we will cover examples for each usage of ssh.
How does SSH work?
The SSH protocol consists of 4 basic steps:
- The client contacts the server to initiate the secure connection with the server.
- The server sends the public key. If the public key is not known by the server, the connection will fail
- Secure parameters are negotiated by the client and server.
- The client or user is successfully authenticated to the remote server.
Note that step 2 assumes that clients expecting to be able to authenticate to the server have already uploaded their public key to the server in some fashion provided by the server administrator.
How to generate an SSH key with ssh-keygen
First, let’s answer a couple of questions about generating a new ssh key.
What is ssh-keygen?
ssh-keygen is an ssh tool used for ssh key generation. Again, this tool will generate two keys, a public and private key. The public key will be uploaded to the servers, and the private key will be kept private by the client for authentication to the servers having the public SSH key.
SSH key generation
To create an ssh key, simply run the ssh-keygen command. This is the simplest way to generate an ssh key with the default options.
The output will be the following. As you can see, an RSA 3072 bit key was generated in the .ssh/id_rsa directory. The .ssh directory, located in the users home directory, is the default directory for ssh keys and is well known to applications looking for an ssh key to use. A cryptographically strong password should be used to secure the key. This is an added layer of protection over just using a stored password for ssh.
misterpki@misterpki:~/ssh-keygen$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/home/misterpki/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/misterpki/.ssh/id_rsa Your public key has been saved in /home/misterpki/.ssh/id_rsa.pub The key fingerprint is: SHA256:hi5JjjSChd0VU338WPa9VbRj6WV4LEoCvIZiLWydbTM misterpki@misterpki The key's randomart image is: +---[RSA 3072]----+ | ++o. . ..| | o . . .... o oo+| |. o..o + ....=o*B| |.. * =.E o..++*| |o oo.o.oSo . .o| | o = o . . | | . + . | | . | | | +----[SHA256]-----+
Instead of going with the default algorithm and key size, they can be specified with the -t and -b flags, respectively. For example, to generate an SSH key with the ecdsa algorithm and 521 bit key size, run the following command:
ssh-keygen -t ecdsa -b 521
The output will be the following:
misterpki@misterpki:~/ssh-keygen$ ssh-keygen -t ecdsa -b 521 Generating public/private ecdsa key pair. Enter file in which to save the key (/home/misterpki/.ssh/id_ecdsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/misterpki/.ssh/id_ecdsa Your public key has been saved in /home/misterpki/.ssh/id_ecdsa.pub The key fingerprint is: SHA256:Ba/Aw/MB5gOCLZVBt4TryiQY33p75UusYMkhdioIAWM misterpki@misterpki The key's randomart image is: +---[ECDSA 521]---+ |oE=++ o . | |=.++ B . o | |.. .. O . o | |... * + | |o+o.o S | |=oo=.o .. | |*...= oo | |.o.....o. | | ..o. .. | +----[SHA256]-----+
The following algorithms are supported:
- RSA – A well established algorithm still commonly used today. Key sizes of 2048, 3072, and 4096 are the most common.
- DSA – No longer recommended.
- ECDSA – Built on top of the DSA algorithm using elliptic curves. A key size of 256, 384, and 521 are the most common. A key size of 521 is most secure but still performant in comparison to RSA key sizes.
- ED25519 – A newer algorithm supported by OpenSSH. Not all clients support it yet.
Additionally, the filename may be specified with the -f option.
ssh-keygen -f ~/my-ssh-key
Configure server with ssh public key
Many system administrators will create an application for their users to upload their ssh public keys, or just ask the users to send them the public key themselves. Some systems, like github, will allow users to upload their ssh key through their web interface. If you are managing the server yourself, you may copy the public key directory to the server with the ssh-copy-id command. To do so, run the following command:
ssh-copy-id -i ~/.ssh/id_rsa.pub firstname.lastname@example.org
ssh-agent is a tool that will remember the users private key and password, so that it only needs to be given one time. Each subsequent time the key is used, ssh-agent will remember the key.
To add an ssh key to your ssh-agent, run the following command:
If you encounter the following error, you need to make sure your ssh agent is running.
Could not open a connection to your authentication agent.
To enable your ssh agent, run the following command:
eval `ssh-agent -s`
SSH Docker Container
After running through the commands above let’s test out how to use ssh when connecting to a docker container. For this example we will begin by creating the following docker compose file.
version: '3.9' services: openssh: image: linuxserver/openssh-server ports: - "2222:2222" environment: - PUBLIC_KEY=./id_ecdsa.pub - USER_NAME=user volumes: - ./config:/config networks: default: ipv4_address: 172.21.0.10 aliases: - openssh-server networks: default: ipam: config: - subnet: 172.21.0.0/24
This example uses the linuxserver/openssh-server docker image. The image uses port 2222 and supports the following environment variables to make the ssh docker container function as desired.
- PUBLIC_KEY – The location of the public key to be copied to the server. The matching private key can then be used for the authentication.
- PASSWORD_ACCESS – The default is false, but we will run through an example of using ssh when password access is allowed.
- USER_PASSWORD – The password for the user connecting with ssh.
- USER_NAME – The user that will be connecting to the ssh server.
docker-compose up --build you can ssh into the running container with the following command:
ssh -p 2222 email@example.com
Note that port 22 is the default port for the ssh command, so in this case it has to be explicitly stated by using the
-p 2222 option.
To test the openssh docker container with an ssh key instead of a password, remove the USER_PASSWORD and PASSWORD_ACCESS variables. Make sure to include your public key in the config/.ssh/authorized_keys directory that is mounted. After a successful test you should see the following result.
In testing this docker container you may run across the following error:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerprint for the ECDSA key sent by the remote host is SHA256:EgScdNs2FNfQxc3BTGXjI+6f/S6+XUNan6zIgHhZ94Q. Please contact your system administrator. Add correct host key in /home/misterpki/.ssh/known_hosts to get rid of this message. Offending ECDSA key in /home/misterpki/.ssh/known_hosts:1 remove with: ssh-keygen -f "/home/misterpki/.ssh/known_hosts" -R "[172.21.0.10]:2222" ECDSA host key for [172.21.0.10]:2222 has changed and you have requested strict checking. Host key verification failed.
This “Host key verification failed” error happens when the host key has changed on the openssh server. For this test, simply follow the instructions to remove the already trusted key from the known_hosts file. If this error is encountered in the wild, first make sure to verify the host key change was valid and not malicious before proceeding.
Let us know in the comments if you have any questions on ssh key generation, ssh key or password authentication, or running the openssh server example in docker.