In our company or home network, we have access to several computers. We probably want to interact with some of them, start some tasks, check some logs, reboot them and so on.
Of course, we are already using ssh to do so. But, if you are still typing a username and password each time you log in somewhere, please stop.
We should stop losing our time, by looking at some excel to get the password or such, and use the power of the public-key cryptography. Smart people created that for a reason.
The principle is simple :
When we are going to connect to the other computer, both
sshd (the daemon waiting for connections) will talk to each other and will check if they can make talk to each other using the keys each of them have. If they succeed, it means we are the one with the good private key (only our computer stores it, nothing else), we are how we claim to be, and therefore we have access.
This keys approach does not only apply to the networks where we ssh.
It applies to the whole Internet, such as GitHub, BitBucket, or anything that has a login and password.
We are not doing pure
ssh command-line with them but we are pushing data into them. Data that need to be authenticated.
That’s why they offer the possibility to add some public keys for our account (through their UI) that will work in pair with the private key we have stored on our local computer.
First, we need to generate those keys on our local computer :
# ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub.
By default, we won’t put any passphrase, even if that can be considered as a bad practice.
That will generate a private key in
-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA/gV3aLUTDenLFw7hkkfNcJT4pbnt7gQVcjga4Rik4+hIU6a6 ... -----END RSA PRIVATE KEY-----
We must never share this, never ever.
Its related public key is in
ssh-rsa AAAAB3NzaC1yc2EAAAADA...slxyu9Ki8Hn6jWR root@computer
The keys are related to our user and hostname.
We are going to copy that line to any server we want to access.
It will use the
user@hostname to find out if it has a public key for us.
It’s popular to add some options to
ssh-keygen, to generate a stronger key and set explicitly the user name in
id_rsa.pub such as:
$ ssh-keygen -t rsa -b 4096 -C "firstname.lastname@example.org"
Now, we are going to copy our public key to the server.
We will be able to identify ourself to the server and get the access.
The default path used by
.ssh/authorized_keys in the home folder of the user we want to connect:
root@local:~# ssh john@server
The path on the server would be:
We can create it manually if it doesn’t exist yet.
Its content is quite simple, one line per public key (several users could connect as john on the server) :
$ cat .ssh/authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAADA...slxyu9Ki8Hn6jWR root@computer ssh-rsa 2cvUZEP4ZuMtElv/Iu6M6...w8Qoa4A3b8a+YNl trainee@macos
As soon as we save the file, we’ll be able to connect from our local computer on the server, no question asked.
root@local:~# ssh john@server john@server:~$
This configuration is a one-way only.
We can’t connect from the server to the local, we need the reverse association.
If we want that, we must perform the same actions but from the other side (generate keys on the server and add the public key to our local computer).
But that’s considered a bad practice: a user on a server should never be able to connect to another computer. We should always exit to our local computer, then connect to the other server. We should not connect nodes between them, it can introduce security issues.
Once we put our public key somewhere, we should never generate again our keys on our computer.
Otherwise we’ll lose the public/private keys association and thus, the ability to connect to the servers we set up. The public key on the servers won’t “match” anymore our local private key.
ssh-keygen will warn us if that’s the case.
Another great feature is to avoid typing the username we want to login with on the server.
Instead of :
root@local:~# ssh john@staging
We’d like to do:
root@local:~# ssh staging
While having automatically john as username on the server.
To do so, we can edit the file
.ssh/config and add something like :
Host staging HostName staging.host.lan User john
We can add as many hosts as we want in this file: it’s simply a list of mappings.
.ssh/config is not only useful to declare Host mappings.
It can contain way more configuration bits, such as :
Host * ServerAliveInterval 60
This can avoid us the famous broken pipe we’ll get if we are inactive in a ssh session.
That will send keep alive packets to be sure the connection stays up.
The keys are not only used by
scp is also compatible (used to copy files from/to another host):
$ scp -r staging:/tmp/logs .
It follows the same rule as
.ssh/config and the set of keys on both sides.
For a better security, our keys should have a passphrase (that we set to blank in our example).
We should also use
ssh-agent to avoid typing it when needed.