Are you trying to figure out what SSH Servers, Clients and Keys are?
This guide is for you.
Basically, SSH keys are an authentication method used to gain access to an encrypted connection between systems and then ultimately use that connection to manage the remote system.
The most common way of connecting to a remote Linux server is through SSH. It provides a safe and secure way of executing commands, making changes, and configuring services remotely.
Here at Ibmi Media, as part of our Server Management Services, we regularly help our Customers to perform SSH queries.
In this context, we shall look into more detailed information about SSH Servers, Clients, and Keys.
We drop into a shell session when we connect through SSH, where we can interact with the server. The commands we type are sent through an encrypted SSH tunnel to execute on the server.
The SSH connection implements using a client-server model. Hence, the remote machine must run a piece of software called an SSH daemon.
It will listen for connections on a specific network port, authenticate connection requests, and spawn the appropriate environment if the user provides the correct credentials.
In addition, the user computer should have an SSH client.
This will have information about the remote host to connect to the username to use, and the credentials to authenticate.
Most of our clients authenticate using passwords or SSH keys. It is recommended to always use SSH keys since they are very secure.
SSH keys are a matching set of cryptographic keys which we can use for authentication. Each set contains a public key that can be shared freely without concern and a private key that should be vigilantly guarded and never exposed to anyone.
To authenticate using SSH keys, a user must have an SSH key pair on their local computer.
On the remote server, we must copy the public key to a file within the user’s home directory at ~/.ssh/authorized_keys.
When we connect to the host to use SSH key authentication, it will inform the server of this intent and the public key to use.
Later, the server checks its authorized_keys file for the public key, generates a random string, and encrypts it using the public key.
Only with the associate private key, we can decrypt this message.
Once the recipient decrypts the message it generates an MD5 hash of this value and transmits it back to the server.
The server already has the original message and the session ID, so it can compare an MD5 hash generated by those values and determine that the client must have the private key.
Here, you will see some common ways of connecting with SSH along with what is SSH Servers, Clients, and Keys.
Let us see how to generate SSH keys on a client machine and distribute the public key to servers to use.
i. Generating an SSH Key Pair
It is the first step towards authenticating with a remote server without a password. We recommend authenticating using SSH keys.
We use a number of cryptographic algorithms to generate SSH keys, including RSA, DSA, and ECDSA.
Generally, we prefer the RSA keys and it is the default key type.
To generate an RSA key pair, we run:
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/demo/.ssh/id_rsa):
It allows us to choose the location to store the RSA private key.
To leave this as the default, press ENTER and it will store them in the .ssh hidden directory in the user's home directory.
The default location will allow the SSH client to find the keys automatically:
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Then we enter a passphrase of an arbitrary length to secure the private key.
By default, we have to enter the passphrase we set here every time we use the private key, as an additional security measure:
While we enter a passphrase, nothing will display as we type.
This is a security precaution.
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:
8c:e9:7c:fa:bf:c4:e5:9c:c9:b8:60:1f:fe:1c:d3:8a root@here
The key's randomart image is:
+–[ RSA 2048]—-+
| |
| |
| |
| + |
| o S . |
| o . * + |
| o + = O . |
| + = = + |
| ….Eo+ |
+—————–+
This procedure generates an RSA SSH key pair, located in the .ssh hidden directory within the user's home directory.
These files are:
a. ~/.ssh/id_rsa: The private key. DO NOT SHARE THIS FILE!
b. ~/.ssh/id_rsa.pub: The associated public key.
This can be shared freely without consequence.
ii. Generate an SSH Key Pair with a Larger Number of Bits
By default, the SSH keys are 2048 bits. Though it's good enough, we can specify a greater number for a more hardened key.
To do this, we include the -b argument with the number of bits we like. Most servers support at least 4096 bits. However, longer keys may not accept for DDOS protection purposes:
$ ssh-keygen -b 4096
If we already have a different key, we can overwrite the previous one:
Overwrite (y/n)?
If we choose “yes”, the previous key will be overwritten and we can no longer log in to servers using that key.
iii. Remove or Change the Passphrase on a Private Key
In case we wish to change or remove the paraphrase, we can do it easily.
To do so, we run:
$ ssh-keygen -p
Enter file in which the key is (/root/.ssh/id_rsa):
We can give the location of the key to modify or press ENTER to accept the default value:
Enter old passphrase:
After we provide the old password, we will have a prompt for the new:
Enter new passphrase (empty for no passphrase):
Enter same passphrase again:
Here, enter the new passphrase or press ENTER to remove the passphrase.
iv. SSH Key Fingerprint
Generally, each SSH key pair share a single cryptographic “fingerprint” to uniquely identify the keys.
To find out the fingerprint of an SSH key, we run:
$ ssh-keygen -l
Enter file in which the key is (/root/.ssh/id_rsa):
We can press ENTER if that is the correct location of the key, else enter the revised location.
In addition, we will have a string that contains the bit-length of the key, the fingerprint, and account and hosts it was created for, and the algorithm:
4096 8e:c4:82:47:87:c2:26:4b:68:ff:96:1a:39:62:9e:4e demo@test (RSA)
v. Copy the Public SSH Key to a Server with SSH-Copy-ID
If we have password-based SSH access to the server, and we have the ssh-copy-id utility installed, this is a simple process.
With this option, we can easily transfer the public key:
$ ssh-copy-id username@remote_host
This will prompt us for the user account's password on the remote system:
The authenticity of host ‘111.111.11.111 (111.111.11.111)’ can’t be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed — if you are prompted now it is to install the new keys
demo@111.111.11.111's password:
Then, the contents of the ~/.ssh/id_rsa.pub key will append to the end of the user account's ~/.ssh/authorized_keys file:
Number of key(s) added: 1
Now try logging into the machine, with: “ssh ‘demo@111.111.11.111′”
and check to make sure that only the key(s) you wanted were added.
We can now log in to that account without a password:
$ ssh username@remote_host
vi. Copy the Public SSH Key to a Server Without SSH-Copy-ID
If we have password-based SSH access to the remote server and no ssh-copy-id utility, we can copy the contents of the public key in a different way.
We can output the contents of the key and pipe it into the ssh command. On the remote side, we can ensure that the ~/.ssh directory exists, and then append the piped contents into the ~/.ssh/authorized_keys file:
$ cat ~/.ssh/id_rsa.pub | ssh username@remote_host “mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys”
The authenticity of host '111.111.11.111 (111.111.11.111)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes
demo@111.111.11.111’s password:
After entering the password, the key will copy, allowing to log in without a password:
$ ssh username@remote_IP_host
vii. Copy the Public SSH Key to a Server Manually
If we do not have password-based SSH access available, we have to add the public key to the remote server manually.
We can find the contents of the public key file by typing:
$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCqql6MzstZYh1TmWWv11q5O3pISj2ZFl9HgH1JLknLLx44+tXfJ7mIrKNxOOwxIxvcBF8PXSYvobFYEZjGIVCEAjrUzLiIxbyCoxVyle7Q+bqgZ8SeeM8wzytsY+dVGcBxF6N4JS+zVk5eMcV385gG3Y6ON3EG112n6d+SMXY0OEBIcO6x+PnUSGHrSgpBgX7Ks1r7xqFa7heJLLt2wWwkARptX7udSq05paBhcpB0pHtA1Rfz3K2B+ZVIpSDfki9UVKzT8JUmwW6NNzSgxUfQHGwnW7kj4jp4AT0VZk3ADw497M2G/12N0PPB5CnhHf7ovgy6nL1ikrygTKRFmNZISvAcywB9GVqNAVE+ZHDSCuURNsAInVzgYo9xgJDW8wUw2o8U77+xiFxgI5QSZX3Iq7YLMgeksaO4rBJEa54k8m5wEiEE1nUhLuJ0X/vh2xPff6SQ1BL/zkOhvJCACK6Vb15mDOeCSq54Cr7kvS46itMosi/uS66+PujOO+xt/2FWYepz6ZlN70bRly57Q06J+ZJoc9FfBCbCyYH7U/ASsmY095ywPsBo1XQ9PqhnN1/YOorJ068foQDNVpm146mUpILVxmq41Cj55YKHEazXGsdBIbXWhcrRf4G2fJLRcGUr9q8/lERo9oxRm5JFX6TCmj6kmiFqv+Ow9gI0x8GvaQ== demo@test
We can copy this value, and manually paste it into the appropriate location on the remote server.
Then on the remote server, create the ~/.ssh directory if it does not already exist:
$ mkdir -p ~/.ssh
Afterward, we create or append the ~/.ssh/authorized_keys file by typing:
$ echo public_key_string >> ~/.ssh/authorized_keys
Now, we will be able to log in without a password.
Now let us look at a few server-side configuration options that can shape the way the server responds and the types of connections allowed.
i. Disable Password Authentication
If we have SSH keys configured, tested, and working properly, it is good to disable password authentication.
To do this, connect to your remote server and open the /etc/ssh/sshd_config file with root or Sudo privileges:
$ sudo nano /etc/ssh/sshd_config
Inside the file, search for the PasswordAuthentication directive. If it is commented out, uncomment it. Set it to no to disable password logins:
PasswordAuthentication no
Once done, save and close the file.
To implement the changes, we restart the SSH service.
On Ubuntu/Debian:
$ sudo service ssh restart
On CentOS/Fedora:
$ sudo service sshd restart
Now, all accounts on the system will be unable to log in with SSH using passwords.
ii. Change the Port that the SSH Daemon Runs On
Sometimes, it is better to change the default port that SSH runs on. This will help decrease the number of authentication attempts from bots.
In order to do that, log in to the remote server. Then open the sshd_config file on the remote system with root privileges:
$ sudo nano /etc/ssh/sshd_config
Once inside, we can change the port that SSH runs on by finding the Port 22 specification and modifying it to reflect the port we need.
For instance, to change the port to 4444, we add:
#Port 22
Port 4444
Eventually, save and close the file.
To implement the changes, we restart the SSH daemon.
On Ubuntu/Debian:
$ sudo service ssh restart
On CentOS/Fedora:
$ sudo service sshd restart
After the daemon restarts, we will need to authenticate by specifying the port number.
iii. Limit the Users Who can Connect Through SSH
For this, we can take a few different approaches, each of which involves editing the SSH daemon config file.
On the remote server, open the below file with root or sudo privileges:
$ sudo nano /etc/ssh/sshd_config
The first method is the AllowUsers directive.
Search for the AllowUsers directive in the file. If it does not exist, we create it anywhere.
After the directive, list the user accounts that should be allowed to login through SSH:
AllowUsers user1 user2
Eventually, save and close the file. Then, we restart the daemon to implement changes.
On Ubuntu/Debian:
$ sudo service ssh restart
On CentOS/Fedora:
$ sudo service sshd restart
In addition, we can use the AllowGroups directive instead. If so, just add a single group that should be allowed SSH access:
AllowGroups sshmembers
Then, save and close the file.
Now, we can create a system group matching the group we specified by typing:
$ sudo groupadd -r sshmembers
Make sure to add whatever user accounts we need to this group:
$ sudo usermod -a -G sshmembers user1
$ sudo usermod -a -G sshmembers user2
Later, restart the SSH daemon to implement changes.
On Ubuntu/Debian:
$ sudo service ssh restart
On CentOS/Fedora:
$ sudo service sshd restart
iv. Disable Root Login
Our Support Techs advice to completely disable root login through SSH once we set up an SSH user account that has sudo privileges.
For that, open the SSH daemon configuration file with root or sudo on your remote server:
$ sudo nano /etc/ssh/sshd_config
Inside, search for a directive called PermitRootLogin. If it is commented, uncomment it. Change the value to “no”:
PermitRootLogin no
Save and close the file.
To implement changes, we restart the SSH daemon.
On Ubuntu/Debian:
$ sudo service ssh restart
On CentOS/Fedora:
$ sudo service sshd restart
v. Allow Root Access for Specific Commands
At times, we might want to disable root access generally, but enable it in order to allow certain applications to run correctly.
For instance, for a backup routine.
We can do it through the root user's authorized_keys file, which contains SSH keys that are authorized to use the account.
Add the key from the local computer that we wish to use to the root user's authorized_keys file on the server.
We will demonstrate with the ssh-copy-id command here:
$ ssh-copy-id root@remote_host
Then, log into the remote server. To adjust the entry in the authorized_keys file, open it with root or sudo access:
$ sudo nano /root/.ssh/authorized_keys
At the beginning of the line with the key we upload, add a command= listing that defines the command that this key is valid for. This should include the full path to the executable, plus any arguments:
command=”/path/to/command arg1 arg2″ ssh-rsa …
Once done, save and close.
Now, open the sshd_config file with root or sudo privileges:
$ sudo nano /etc/ssh/sshd_config
Find the directive PermitRootLogin, and change the value to forced-commands-only:
PermitRootLogin forced-commands-only
Eventually, save and close the file. Restart the SSH daemon to implement changes.
On Ubuntu/Debian:
$ sudo service ssh restart
On CentOS/Fedora:
$ sudo service sshd restart
vi. Forward X Application Displays to the Client
We can configure the SSH daemon to automatically forward the display of X applications on the server to the client machine. For this to function correctly, the client must configure and enable an X windows system.
To enable, login to the remote server and edit the sshd_config file as root or with sudo privileges:
$ sudo nano /etc/ssh/sshd_config
Search for the X11Forwarding directive. If it is commented out, uncomment it. Create it if necessary and set the value to “yes”:
X11Forwarding yes
Save and close the file. Restart the SSH daemon to implement these changes.
On Ubuntu/Debian:
$ sudo service ssh restart
On CentOS/Fedora:
$ sudo service sshd restart
To connect to the server and forward an application’s display, we have to pass the -X option from the client upon connection:
$ ssh -X username@remote_host
Graphical applications started on the server through this session will display on the local computer.
Moving ahead, we will focus on some adjustments that we can make on the client-side of the connection.
i. Define Server-Specific Connection Information
On the local computer, we can define individual configurations for some or all of the servers we connect to. We can store it in the ~/.ssh/config file, which is read by the SSH client each time it is called.
Initially, create or open this file in a text editor on the local computer:
$ nano ~/.ssh/config
Inside, we can define individual configuration options by introducing each with a Host keyword, followed by an alias.
For example,
Host testhost
HostName your_domain
Port 4444
User demo
Then we connect to your_domain on port 4444 using the username demo:
$ ssh testhost
We can also use wildcards to match more than one host.
Make note that later matches can override earlier ones. So, we should put the most general matches at the top.
For instance, we could default all connections to not allow X forwarding, with an override for your_domain by having this in your file:
Host *
ForwardX11 no
Host testhost
HostName your_domain
ForwardX11 yes
Port 4444
User demo
Eventually, save and close the file.
ii. Keep Connections Alive to Avoid Timeout
If in case we disconnect from SSH sessions before we are ready, it is possible that the connection is timing out.
We can configure the client to send a packet to the server every so often in order to avoid this situation:
We can configure this in the ~/.ssh/config file. Open it now:
$ nano ~/.ssh/config
If one does not already exist, at the top of the file, define a section that will match all hosts. Set the ServerAliveInterval to “120” to send a packet to the server every two minutes.
This is enough to notify the server not to close the connection:
Host *
ServerAliveInterval 120
Eventually, save and close the file.
iii. Disable Host Checking
By default, when we connect to a new server, we can see the remote SSH daemon's host key fingerprint.
The authenticity of host ‘111.111.11.111 (111.111.11.111)’ can’t be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes
This is to verify the authenticity of the host we are attempting to connect to and spot malicious instances.
In certain circumstances, we may wish to disable this feature. This can be a big security risk.
To make the change, open the ~/.ssh/config file on the local computer:
$ nano ~/.ssh/config
If one does not already exist, at the top of the file, define a section that will match all hosts.
Set the StrictHostKeyChecking directive to no to add new hosts automatically to the known_hosts file. Set the UserKnownHostsFile to /dev/null to not warn on new or changed hosts:
Host *
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Then we can enable the checking on a case-by-case basis by reversing those options for other hosts. The default for StrictHostKeyChecking is ask:
Host *
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Host testhost
HostName your_domain
StrictHostKeyChecking ask
UserKnownHostsFile /home/demo/.ssh/known_hosts
This article covers important information about SSH Servers, Clients and Keys. Use SSH keys for authentication when you are connecting to your server, or even between your servers.
They can greatly simplify and increase the security of your login process.
When keys are implemented correctly they provide a secure, fast, and easy way of accessing your cloud server.
Turn off password authentication Linux:
With SSH key authentication configured and tested, you can disable password authentication for SSH all together to prevent brute-forcing. When logged in to your cloud server.
1. Open the SSH configuration file with the following command.
$ sudo nano /etc/ssh/sshd_config
2. Set the password authentication to no to disable clear text passwords.
PasswordAuthentication no
3. Check that public key authentication is enabled, just to be safe and not get locked out from your server. If you do find yourself unable to log in with SSH, you can always use the Web terminal control panel.
PubkeyAuthentication yes
Then save and exit the editor.
4. Restart the SSH service to apply the changes by using the command below.
$ sudo systemctl restart sshd
With that done your cloud server is now another step along towards security.
Malicious attempts to connect to your server will results in authentication rejection, as plain passwords are not allowed, and brute-forcing an RSA key is practically impossible.