How SSH (Secure Shell) Works
SSH (secure shell) is an encrypted and secure protocol that is used to create a connection between a local computer and a remote server. When we build a website or application, we need to put it on the remote server to access it publicly. But the question is, how do we configure our server remotely? How do we make sure our server is working fine? How to transfer files from our local computer to the server? How to run commands/scripts on our server, etc? We can’t visit the server’s location, because the server can be in have different country from our current location. That’s why we need to use SSH to connect our local computer to our remote server.
We can use SSH for a variety of use cases :
- Server management like install updates, change configuration, monitor the server, etc
- Transfer file from local to remote server (SCP/SFTP)
- Tunneling / Port forwarding
- Git Interaction
- etc
There are many other uses for SSH, but for now, we will focus on its basic usage first which is a connection from our local computer to the server. So in this article, we will talk about how to connect our server using SSH and how SSH connection works starting from TCP connection setup, SSH version check, key exchange process, and client authentication (password authentication and public key authentication).
SSH Example
Before explaining how SSH works, we need to understand what SSH looks like. You can see this image below.
So that is an example of how we connect from the local computer (samuelricky@samuels-Mackbook-Pro) to our remote server (samuelricky@localhost with IP address 192.168.64.10). It’s simply just run the command :
ssh {user on remote server}@{ip address of remote server}After that, we just need to write “yes” because that is the first time to connect the server. As we see in the image above, we successfully connect our remote server and when we run the “ls” command, it will show all the content of the current directory. We can do anything like copy files from the local to the remote server, change configuration on the remote server, add users, create files, etc.
Maybe you ask, why in the example above, the remote server didn’t use a public IP (192.168.64.10 is a private IP). So since this is only an example, I demonstrate by using a virtual machine that is already installed on my PC, that’s why it still uses private IP. But for the real case, if we want to connect to our remote server, the command is still the same.
How SSH Works
So now, what happens when we create an SSH connection from our local computer to our remote server?
There are 4 steps :
- TCP Connection Setup
- SSH Version Check
- Key Exchange Process
- Client Authentication
So after we hit enter this command :
ssh {user on remote server}@{ip address of remote server}There are 4 processes happen in the background. If you read other articles, it may contain 5 or 6 or maybe only 3. But, it’s the same, it just has a different grouping. So let’s deep dive one by one.
1. TCP Connection Setup
Before the client communicates with the server, of course, the client must create a connection first. So the client will set a new TCP connection to the server that contains a 3-way handshake process. 3 ways handshake is just setting up reliable connection between client and server. You can see this video if you curious about the details how 3-way handshake process works https://www.youtube.com/watch?v=xMtP5ZB3wSk. So this is a basic process before the client wants to connect to the server.
2. SSH Version Check
After the client and server have done 3 ways handshake, now it’s time to begin the SSH version checking. Here is the sequence of this process :
- The server will start sending the SSH version string to the client. Ex: “SSH-2.0-OpenSSH_7.9”. That string indicates that the server uses SSH version 2.0 and OpenSSH 7.9
- The client will send an SSH version string to the server as well. Ex: “SSH-2.0-OpenSSH_8.6”. That string indicates that the client uses SSH version 2.0 and OpenSSH 8.6
- Both the server and client will check the SSH version. If one of them finds that the SSH version does not match, then it will terminate the connection. In this case, the version is the same, which is SSH 2.0.
- If there is no explicit termination signal, then it will go into the next step which is a key exchange process.
So SSH version checking is a quite straightforward process, it’s just check the SSH version same or not, if same then continue to the next step.
3. Key Exchange Process
Once the SSH version is compatible with each other, then now client and server begin the key exchange process. SSH is a secure shell protocol, so every communication inside SSH must be secure. That’s why here we need a key exchange process to make sure SSH communication is encrypted securely. So you can think key exchange is just generate a key that used to encrypt entire communication. If you see the image above, it looks like confusing at the beginning, but it should be easy to understand once you read this explanation.
Determine Key Exchange Algorithm
The first step is client and server need to agree on the key exchange algorithm. That algorithm will used to generate shared secrets between client and server. So to determine the key exchange algorithm, here are the steps :
- The client will propose the list of exchange algorithms to the server (ex: Diffie-Hellman (DH) Group 1, Elliptic Curve Diffie-Hellman (ECDH), etc).
- The server will select the algorithm it supports and inform to client.
- Then client and server will agree with the selected key exchange algorithm.
So the purpose is only one, which is to determine a key exchange algorithm, that will be used to generate a shared secret. Maybe you ask, what is a shared secret? So shared secret is a value that is generated independently by the client and server without being transmitted over the network. We will discuss more about shared secret in the “Shared Secret Generation” section. Remember, until here client and server already agreed with the algorithm, but not executed the algorithm yet.
Server Authentication
Now, before client and server execute the algorithm, the client needs to make sure the server is correct. Imagine if you want to call your boss, of course, you need to validate whether the voice is coming from your boss or not. If not, then it’s very dangerous because you can give confidential secrets to someone who should not get that information. So that’s why server authentication is quite important before executing the algorithm, it can prevent man-in-the-middle attacks.
So here is what happened :
- After the client and server agree on a selected algorithm, the server gives the public key to the client. Remember, the public key is public, no need for any encryption.
- The client will check the server’s public key on the ~/.ssh/known_hosts file. That file contains all public keys of servers that have ever been connected from the client. So once the client receives the public key, the client will check that public key on the known_hosts file to make sure the listed server’s IP address is correct with the server’s IP address that is used to connect. If not listed, then the client will create a new “row” describing the server IP address & public key on that file. If the server’s public key already exists in the known_hosts file but it’s incorrect with the public key that got from the server, then the SSH client will terminate the connection. Because it could be an indication of a man-in-the-middle attack.
Shared Secret Generation
Ok now the client already trusts the server, The next step is client and server will execute the algorithm that was already agreed upon before. The result of the algorithm is a shared secret (an identical value that is generated independently by the client and server without transmitting over the network). Maybe you ask, how is that possible to generate a same value without transmit over the network? Yeah, that’s how the key exchange algorithm magic, so that algorithm will make the client and server able to generate value (that we called shared secret) independently and the value will be same.
If you are curious about how the algorithm works, you can see in this video : https://www.youtube.com/watch?v=NmM9HA2MQGI. But we need to understand, in real-world scenarios, the value of shared secret can be a very large number.
Session Key Generation
Before we continue, until here client and server already have :
- Same shared secret (generated by the agreed algorithm)
- Same SSH version
- Same Information about the server’s public key
- Same Information about key exchange message (ex: algorithm selection)
- Same Information about protocol details (IP address, port, etc)
Now it’s time to put it all together into the hash algorithm (e.g., SHA-256) to generate a session identifier (session identifier is a value that is used as an identifier on each SSH session). So both the client and server will generate the same session identifier by hashing the data above. Maybe you ask, how can it produce the same session identifier value? Yes, the result will be same because the data (shared secret, SSH version, server’s public key, etc) are same, and the hash algorithm is also the same, so the result of the session identifier will be same.
Get Samuel Ricky Saputro’s stories in your inbox
Join Medium for free to get updates from this writer.
Ok, now the client and server already have the same session identifier. The next step is they will continue to put the same session identifier, same shared secret, same SSH version, same nonces (random value, but client and server have same nonces), same context (purpose of this key), etc to perform key derivation process. Remember, the input will be the same and the output will also same. But now it performs a key derivation process, not a hash algorithm.
What is the key derivation process and what is the result then? The key derivation process is used to generate multiple keys (it is generated by an algorithm like PBKDF2). So once the client and server perform the key derivation process, it will produce keys :
- Client-to-server encryption key (K_C2S) => used for encrypting data sent by client to server and will used by server to decrypt the data.
- Server-to-client encryption key (K_S2C) => used for encrypting data sent by server to client and will used by client to decrypt the data.
- Client to server MAC key (K_MAC_C2S) => used to verify the integrity of the data sent by the client to server
- Server to client MAC key (K_MAC_S2C) => used to verify the integrity of the data sent by the server to the client
So once client and server already have that keys, it means every communication must be encrypted by using that keys. So until here, the SSH communication between client and server already encrypted securely.
Summarize
Hopefully, you still understand it. Here is the summary of the key exchange process :
- Determine key exchange algorithm: The client & server agreed with the key exchange algorithm
- Server authentication: The client makes sure the destination server is correct.
- Shared secret generation: Client & Server execute an exchange algorithm to generate a shared secret
- Session identifier generation: Client & server hash all values (shared secret, SSH version, public key, etc) together to produce session identifier
- Session key generation: Client & server put all generated values (session identifier, shared secret, SSH version, etc) to the key derivation function and it will produce session keys that contains 4 keys (K_C2S, K_S2C, K_MAC_C2S, K_MAC_S2C)
So after that process finish, the client and server will use the session keys to transfer the data over the network. It means, the client and server already have strong encrypted communication, and it’s already secure to transfer the data. The next step is we continue to client authentication which will transfer sensitive information. That’s why before we transfer sensitive information, we must have strong encrypted communication first.
4. Client Authentication
So once the communication is already encrypted securely, we continue to client authentication. The client authentication process will make sure the origin of the client is correct (not come from an attacker that pretends to be an original client). So here is how it works :
Determine Authentication Method Priorities
It’s similar to process number 3 (Key Exchange Process) where the client and server must agree with the algorithm that they will use. Now in this process, the client and server must agree on a list of authentication methods that will used. Why list? Why is not only 1 method used? Because the client can attempt more than 1 authentication method. Let’s say the agreed list of authentication methods is: public key authentication, password authentication, and keyboard-interactive authentication. Then client will try to authenticate with the public key, if fails then the client will try to enter a password, if still fails client will try the keyboard-interactive method.
The negotiation process is simple :
- The server just give a list of supported authentication methods to client
- The client will filter it based on what capabilities of the client
- Then now the list of authentications is ready
- The client starts authenticating 1 by 1 based on top priority first.
If we want to determine the supported client’s authentication method/server’s authentication method like disable password authentication or disable other authentication method, then we can configure it via SSH configuration. I’ll explain about SSH configuration on other article later.
Try Authenticate With All Agreed Method Until Success
So, once the client already has a list of authentication methods that will be used, then the client will start to authenticate 1 by 1. In this article, I’ll explain only 2 authentication methods that are used by most of the system, which are public key authentication and password authentication.
Password Authentication Method is the simplest way. When the client connects to the server, the server just asks for the password, then the client just needs to fill in the password, and done. When we first time SSH to our server, usually we only can use the password authentication method. This is the simplest method but not recommended, because it’s not safe.
Public key authentication is a bit complex but it is much more secure other than password authentication. Basically, it will work only when
- The client already has public & private key
- The client’s public key already stored on the server
Remember, the public key is a public value that can be shared anywhere, while the private key is a private value that must be stored only on the client and should not shared with anyone. In this article, I’ll explain a bit about how to generate public & private keys. So to generate it, it’s quite simple, just open the terminal and run
ssh-keygen -t rsa -b 4096 -C "YOUREMAIL"Then you will get prompt like this :
Enter file in which to save the key (/home/user/.ssh/id_rsa):You can just type “id_rsa”, then you will get a prompt like this :
Enter passphrase (empty for no passphrase):You can fill your passphrase or you can leave it as empty. Then you will get 2 new files :
- Client’s private key : ~/.ssh/id_rsa
- Client’s public key : ~/.ssh/id_rsa.pub
Now what you need to do is just put the public key into your server. To do that, you just need to run this command
ssh-copy-id user@hostnameHere is an example
So until here, we already put the client’s public key to our server. The next step is just to run SSH again like this.
Then finish !
But how actually it works? Here is how it works :
- Checklist before use public key authentication: Remember, before we use public key authentication, we must put client’s public key to server.
- Start SSH connection: After client’s public key already put on the server, now we can start SSH connection by run command “ssh user@ipaddress”.
- The client sends the public key to the server: Once we hit enter after type ssh command, what happen in the background is client will send the public key to the server. Remember public key is public, so it’s fine.
- Server validates that public key: Then the server will check that public key in ~/.ssh/authorized_keys. The client’s public key must exist on that file because previously we already copy to that file. If not exist, then the server will reject the authentication. That’s why in the beginning, we need to put the client’s public key to the server first.
- The server gives a “challenge” to the client by giving a random value: Then the server will give a “challenge” (random message) to the client.
- Client signs the “challenge” by using the client’s private key: Now the client just needs to sign the “challenge” (random message) using the private key. Remember, the client will sign, not encrypt, it’s different! But I’ll explain in another article why it’s different. When the client signs, the “challenge” will become a signed challenge. No one can open it unless they have the client’s public key.
- Client sends signed “challenge” to server: After the client already signed the “challenge”, now client needs to send the signed “challenge” to the server since the server will validate it by using the client’s public key
- The server verifies the signed “challenge” from the client by using the client’s public key: Once the server receives the signed “challenge”, the server will verify the signed “challenge” by using the client’s public key that stored on ~/.ssh/authorized_keys.
- If it a success, then authentication is a success, else it’s failed: After that, the server will check, if it’s matches, and then the server can trust the client. If not match, then the server will reject it.
Once it’s success, it means client and server already trust each others. So we can start transfer file, monitor the server, add users, etc.
Summary
So when we connect our server via SSH, it will begin with TCP connection setup to make sure the client and server have a reliable connection, then it continues with SSH version check to make sure the SSH version is the same, then it will start key exchange process to build an encrypted connection between client & server, then finally it will execute client authentication to make sure the client has access to the server. After that finish, client and server can transfer data each others.
SSH is quite important when we want to connect from our local computer to our server because it uses encrypted communication that makes data transmitted securely. It also ensures that the client and server don’t get attacked by a man-in-the-middle attack. So hopefully this explanation can help you understand how SSH works.
Thank you.




