SSH#

This page shows aspects of working with the ssh connection. We will consider an example where an ssh connection is established from one Docker container to another.

Note: strongly recommended to run this notebook in a secure environment it may display sensitive information related to ssh keys. Environment requires docker installation. However id doesn’t have its won docker build - use setup described here.

Set up#

Ssh host would be represented by docker container, the following cell runs docker container which we’ll use as ssh host.

docker run -dit --rm --name ssh_host -p 22:22 alpine &> /dev/null

Install and start the ssh server.

docker exec ssh_host sh -c " 
# openssh instalation
apk add -q openssh
# generating default host keys - they are necessary for running ssh server
ssh-keygen -A
# running ssh server
/usr/sbin/sshd -D &" &> /dev/null

To make sure that your ssh server is configured correctly, use the nc <host> <port> command. You should be able to read corresponding message from the server. The following cell shows this option for our configuration.

nc -w 1 localhost 22
SSH-2.0-OpenSSH_9.9

In the current environment, we only need the ssh client.

apk add -q openssh-client
7  0%                                                                           8

Generating key#

You need to generate an ssh key. It consists of two parts, a public key and a private key. You can generate it wherever you like. But in our example we will consider the most straightforward option - generating it on the client.

You can just run ssh-keygen and follow the CLI’s instructions. It’ll ask for filepath for the key and passphrase. However, due to the limitations of the jupyter notebook we are using for the presentation, we need to specify some options:

  • t rsa: This option specifies the type of key algorithm to use. In this case, it specifies RSA as the algorithm. RSA is a widely used asymmetric encryption algorithm.

  • N "" : This option sets the passphrase (or password) for the generated key. In your command, it is set to an empty string, effectively creating a key without a passphrase. It means that anyone with access to the private key file can use it without providing a passphrase.

  • f /root/.ssh/id_rsa: This option specifies the filename and path where the generated key pair will be stored. In this case, it will be stored in the /root/.ssh/ directory with the filename id_rsa. The id_rsa file will contain the private key, while the id_rsa.pub file (automatically generated) will contain the public key.

ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa
Generating public/private rsa key pair.
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:ckjSwAPtmsgMsQ+9nmo4q8qHYUI/BRT5a7Zl9TjE1VI root@d0d8db92d18f
The key's randomart image is:
+---[RSA 3072]----+
|  o*+       oE   |
|.  o+o     o .   |
| + .+.o . . .    |
|+.. .= . +       |
|=+.+. + S o      |
|o==o + = o .     |
|+.o.+ +   .      |
|+oo. .           |
|O=.              |
+----[SHA256]-----+

After all I’ll have id_rsa and id_rsa.pub files in my the sepcified for ssh keys folder.

ls -l /root/.ssh
total 16
-rw-------    1 root     root          2602 Feb  7 13:49 id_rsa
-rw-r--r--    1 root     root           571 Feb  7 13:49 id_rsa.pub
-rw-r--r--    1 root     root          6452 Feb  7 13:43 known_hosts

This is what the private key looks like.

cat /root/.ssh/id_rsa | head -n 10 | tail -n 5
Ijsp5A3yZUFB9RT6AwlvZ+tJxIts+rQGgHIRiHn1/ljZlhIIEKZKN7JV3IcrEfu9h8/uFo
6vye3rFqAzHTEWBLhj76mWr3WEAVubTcA6s3OTvAzFAqEeEDSlQ1g0EWpiIwSgNX3uxrxJ
jBulPmciF8mZ+4d8gp+0oAo2O3lbh9UeyxiZlMXowo7Vs9/e15HMjw4TJZLXNFAMc5XZha
nPnaxBioBMdJ2fVBxeJ3/5hm1VeKT5XhOjKzAN7gKhdQmziv52SKokqyVmXZWe89uCwp/l
/4ofy/CKYdcAQMByiWrJuB7lEgbsJrNvCREgIq/BAAAFiMFBm6vBQZurAAAAB3NzaC1yc2

Note Only a few lines can be printed here because Githab, which I use to save these pages, sends me notifications that I have credentials leaks.

And here is what the public key looks like.

cat /root/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC3tvsJRX1uxF+aiIkkFmNw+y0XQJ6lRbEBe6xR4XNUS9QQsjobl+PixLASVfMv9X2eEBxAH3reYvP/nham4+ztix+90Diad/n7ICKQB5wzegtRvSd6iwHF1jhLfUkLjqOzSzFJEND5LXdFMNKP/CnxcIHFYiPTSPS1RmMhwXAMKuVJfub+RbpVh0guTe3AJAkiOynkDfJlQUH1FPoDCW9n60nEi2z6tAaAchGIefX+WNmWEggQpko3slXchysR+72Hz+4Wjq/J7esWoDMdMRYEuGPvqZavdYQBW5tNwDqzc5O8DMUCoR4QNKVDWDQRamIjBKA1fe7GvEmMG6U+ZyIXyZn7h3yCn7SgCjY7eVuH1R7LGJmUxejCjtWz397XkcyPDhMlktc0UAxzldmFqc+drEGKgEx0nZ9UHF4nf/mGbVV4pPleE6MrMA3uAqF1CbOK/nZIqiSrJWZdlZ7z24LCn+X/ih/L8Iph1wBAwHKJasm4HuUSBuwms28JESAir8E= root@d0d8db92d18f

Copying public key#

The list of public keys that have access to the server can be found ~/root/.ssh.authorized_keys file.

docker exec ssh_host mkdir -p /root/.ssh
docker exec ssh_host \
    sh -c "echo $(cat ~/.ssh/id_rsa.pub) >> /root/.ssh/authorized_keys"

Getting access#

If setup is correct, you can get ssh from the client server to the host server using the command ssh <user_name>@<host_name>. In our example try:

docker exec -it ssh_client ssh root@ssh_host

So here is a rather tricky case - we have access to the ssh_host CLI through the ssh_client CLI.


The following cell adds some files to the server via ssh.

ssh -o StrictHostKeyChecking=no root@localhost touch file{1..5}

To make sure that ssh really worked, the following cell shows the created files in the ls output.

docker exec ssh_host ls /root
file1
file2
file3
file4
file5

Note The -o StrictHostKeyChecking=no option is used here to prevent the client from asking if it needs to add host to the list of known hosts.