Let's talk about SSH a little bit.
First of all, you might ask yourself, what is SSH?
Well, in short, SSH stands for Secure Shell.
Ok, but what does it mean?
It allows you to gain, cryptographically secured, command-line (shell) access on a remote machine.
What is a remote machine?
Remote machine can be your web or build server, or any other machine that can be accessed via SSH.
On Linux and macOS, command-line SSH client usually comes preinstalled with the system. As such, it can be used directly in the terminal window. For Windows, SSH client is not usually installed with the system, but there are plenty of SSH clients that can be installed manually. In this article, focus will be on macOS.
What is an SSH client?
It is a program that allows establishing secure and authenticated SSH connections with SSH servers. It will be running on your machine.
What is an SSH server?
It is a program that is running on a remote machine and listening for SSH connection.
So, as you can see, SSH works on the client-server
model. Where the server is constantly listening for new SSH connection requests, usually on TCP port 22, and the client can initialize SSH connection with the server at any point in time.
Password based authentication
Establishing an SSH connection is pretty straightforward. But, before it can be done, you need to know username
and hostname
, or IP
address, of the server.
So basically, you will use the SSH client, on your machine, to connect with the SSH server on the remote machine. Assuming you are on macOS or Linux, you can run the following command to connect via SSH.
ssh <username>@<hostname>
username
- server user.hostname
- server host. If not known, IP address can be provided instead.
If you are connecting with the server for the first time, you will be asked to confirm server identity. If you confirm it, the public key of the server will be saved into your local ~/.ssh/known_hosts
file. Next time you try to connect, your known_hosts
file will be checked and since the server public key is already added there, this step will be skipped.
As a next step, you will be asked for a password to confirm that you are authorized to access the server. If provided password is not correct, connection will be rejected.
As you might have already noticed, every time you want to establish an SSH connection with the remote machine, you will have to enter a password. This approach is good if you don't access the server frequently, but even so, it is still better to use SSH keys instead.
If you are currently connected via SSH, go ahead and run following command.
logout
It will terminate the currently running SSH session. Now, let's check out what are those SSH keys.
SSH keys basics
SSH protocol uses SSH keys as an access credential. This means that, instead of the password that was used before, you can use SSH keys to connect to the server. Other than that, SSH keys are much more robust, longer and complex than any password could ever be. As such, they are a better and more secure method of authentication.
SSH uses a pair of keys, public key and private key. They are generated using public key cryptographic algorithms and most common of them are RSA and DSA. These algorithms are based on a mathematical formula that takes 2 very large prime numbers and outputs public and private key.
Public key can be shared freely with others, while private key must be saved securely and only the key owner should know its value.
Session key
There is one more important key called session key. This key is negotiated by both parties, client and server, during the connection process. Session key is generated using a version of the Diffie-Hellman algorithm. This algorithm works in a way that both parties contribute equally to the generation of the session key. Because of the nature of the algorithm, the session key represents a shared symmetric key. It means that this key can be used for both encryption and decryption.
Authentication flow
Before a key-based connection can be established, something called SSH handshake is going to happen. SSH cryptographic handshake ensures that both parties, client and server, are authenticated. Below is a sample of communication between client and server during SSH handshake.
- Client initializes SSH connection with the server and sends ID of its public key.
- Server checks
~/.ssh/authorized_keys
file of the user that the client is attempting to log in.
If a public key with matching ID is found, the server generates a random number and uses the public key to encrypt the message.
Server sends the encrypted message back to the client. - Client decrypts the number using its private key.
- Client combines decrypted number and shared session key to generate MD5 hash value.
- Client sends this MD5 hash back to the server as an answer to the encrypted number message.
- Server uses a shared session key and the original number to calculate MD5 hash value.
- Server compares its calculation with the one that the client has sent.
- If two values are matched, it proves that the client has the correct private key.
Client is authenticated and connection is established.
If the SSH handshake was successful, connection between client and server will be established. This process is secure since it relies on cryptographic authentication to establish connection between client and server.
Generating SSH keys
By now, you might ask yourself, how can I generate those SSH keys?
SSH keys can be generated really quickly using following command.
ssh-keygen -t rsa -b 4096 -C <email_address> -f <file_name>
This command will create SSH keys using your the email address as a label. Optionally, you can pass -f
flag where you can specify file name for SSH keys.
If -f
flag is not provided, you will be prompted to provide file name or you can press enter
to accept default. If you press enter
, file name id_rsa
will be used as a default.
Next, you will be asked to enter a passphrase. If a passphrase is provided, it will be required when ever key is used. This can be useful if someone gains access to the machine where private key is stored, since they will not be able to use private key without correct passphrase.
When command finishes running, you shold see following files in your ~/.ssh
directory.
├── <file_name>├── <file_name>.pub└── ...
File with the extension .pub
contains the data about public key and it can be shared with anyone else. The other file, without .pub
extension, contains the data about private key and it needs to stay secure.
Enable key-based authentication
To enable key-based authentication with a server, you need to tell the server about your public key. To do so, you need to add your public key to ~/.ssh/authorized_keys
file on the server.
cat ~/.ssh/<file_name>.pub | pbcopy
This command will copy your public key to the clipboard. Now, coppied public key needs to be added into the ~/.ssh/authorized_keys
file on the server. To do so, login to the server using password authentication.
Once you gain access to the server, run following command.
pbpaste >> ~/.ssh/authorized_keys
It will paste your, previously copied, SSH key and append it at the end of the content in ~/.ssh/authorized_keys
file.
Execute following command to confirm that your public key is saved.
cat ~/.ssh/authorized_keys
You should see content of authorized_keys
file printed in terminal window. Your public key should be printed as a last item.
Now, execute logout
command to terminate current SSH session.
Next time you start a new SSH connection with the same server, authentication will be made using SSH keys.
This way of authentication is often used on CI/CD to automate processes and authenticate machines without user interaction.
Conclusion
Today, SSH and SSH keys are incredibly important and used everywhere. From online services to automatically authenticate each other to your Github account to push the code changes.
You don't have to be a Secure Shell expert by any means, but knowing the basics can come a long way. I hope this post has provided you with just that - the basics.