SSH is a server login tool that provides password login and key login.

However, there is a third method of SSH login, and that is the certificate login. In many cases, it is the more logical and secure method of login, and this article describes that method of login.

Disadvantages of non-certificate login

Password login and key login, both have their disadvantages.

Password login requires entering the server password, which is very cumbersome and insecure, with the risk of brute force cracking.

Key login requires the server to save the user’s public key, and also requires the user to save the fingerprint of the server’s public key. This is inconvenient for large organizations with multiple users and multiple servers, and if an employee leaves, his public key needs to be removed from each server.

What is the certificate login?

Certificate login is designed to solve the above drawbacks. It introduces a Certificate1 authority (CA), which issues server certificates to trusted servers and user certificates to trusted users.

When logging in, users and servers do not need to know each other’s public keys in advance, but only need to exchange their respective certificates and verify whether they are trusted.

There are two main advantages of certificate login: (1) Users and servers do not need to exchange public keys, which is easier to manage and has better scalability. (2) The certificate can set the expiration time, while the public key has no expiration time. For different situations, certificates with very short expiration dates can be set to further improve security.

Flow of certificate login

Before SSH certificate login, if there is no certificate yet, you need to generate a certificate. The specific methods are: (1) both the user and the server send their public keys to the CA; (2) the CA uses the server public key to generate the server certificate and send it to the server; (3) the CA uses the user public key to generate the user certificate and send it to the user.

Once the certificate is available, the user can log in to the server. The whole process is handled automatically by SSH and is not perceived by the user.

In the first step, SSH automatically sends the user certificate to the server when the user logs in.

In the second step, the server checks whether the user certificate is valid and whether it is issued by a trusted CA.

In the third step, SSH automatically sends the server certificate to the user.

In the fourth step, the user checks whether the server certificate is valid and whether it is issued by a trusted CA.

Step 5, both parties establish a connection and the server allows the user to log in.

Generate the key for the CA

The prerequisite for certificate login is that there must be a CA, which is essentially a pair of keys, no different from other keys, and the CA uses this pair of keys to issue the certificate.

Although CA can issue user certificate and server certificate with the same pair of password, it is better to issue them separately with different keys for security and flexibility. Therefore, the CA needs at least two pairs of keys, one for issuing user certificates, assumed to be called user_ca, and the other for issuing server certificates, assumed to be called host_ca.

Use the following command to generate user_ca.

1
2
# Generate the key for the CA to issue the user certificate
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/user_ca -C user_ca

The above command will generate a pair of keys in the ~/.ssh directory: user_ca (private key) and user_ca.pub (public key).

The meaning of each parameter of this command is as follows.

  • -t rsa : Specify the key algorithm RSA.
  • -b 4096 : Specify the number of bits of the key is 4096 bits. For low security requirements, this value can be smaller, but should not be less than 1024.
  • -f ~/.ssh/user_ca : Specify the location and filename of the generated key.
  • -C user_ca : Specify the identification string of the key, which is equivalent to a comment and can be set at will.

Use the following command to generate host_ca.

1
2
# Generate the key for the CA to issue the server certificate
$ ssh-keygen -t rsa -b 4096 -f host_ca -C host_ca

The above command will generate a pair of keys in the ~/.ssh directory: host_ca (private key) and host_ca.pub (public key).

Now, the ~/.ssh directory should have at least four keys.

  • ~/.ssh/user_ca
  • ~/.ssh/user_ca.pub
  • ~/.ssh/host_ca
  • ~/.ssh/host_ca.pub

CA issues server certificates

After you have a CA, you can issue a server certificate.

To issue a certificate, you need the server’s public key in addition to the CA’s key. Generally, the key /etc/ssh/ssh_host_rsa_key is already generated when the SSH server (usually sshd) is installed. If not, you can use the following command to generate it.

1
$ sudo ssh-keygen -f /etc/ssh/ssh_host_rsa_key -b 4096 -t rsa

The above command will generate ssh_host_rsa_key (private key) and ssh_host_rsa_key.pub (public key) in /etc/ssh directory. Then, you need to copy or upload the server public key ssh_host_rsa_key.pub, to the server where the CA is located.

Once uploaded, the CA can use the key host_ca to issue the server certificate for the server public key ssh_host_rsa_key.pub.

1
$ ssh-keygen -s host_ca -I host.example.com -h -n host.example.com -V +52w ssh_host_rsa_key.pub

The above command generates the server certificate ssh_host_rsa_key-cert.pub (the server public key name plus the suffix -cert). The meaning of each parameter of this command is as follows.

  • -s : Specify the key for the CA to issue the certificate.
  • -I : The identity string, which can be set arbitrarily and is equivalent to a comment to distinguish the certificate, and can be used to revoke the certificate in the future.
  • -h : Specify that the certificate is a server certificate, not a user certificate.
  • -n host.example.com : Specify the domain name of the server, indicating that the certificate is valid only for that domain. If there is more than one domain name, use comma to separate them. When a user logs in to this domain server, SSH uses this value of the certificate to distinguish which certificate should be used to issue to the user and to prove the trustworthiness of the server.
  • -V +52w : Specify the validity of the certificate, in this case 52 weeks (one year). By default, the certificate is valid forever. It is recommended to use this parameter to specify the validity period, and it is better to have a shorter validity period, up to 52 weeks.
  • ssh_host_rsa_key.pub: the server public key.

After generating the certificate, you can use the following command to view the details of the certificate.

1
$ ssh-keygen -L -f ssh_host_rsa_key-cert.pub

Finally, set permissions for the certificate.

1
$ chmod 600 ssh_host_rsa_key-cert.pub

CA issues user certificates

Next, the CA is used to issue the user certificate. This requires the user’s public key, and if it is not available, the client can generate a pair of keys with the following command.

1
$ ssh-keygen -f ~/.ssh/user_key -b 4096 -t rsa

The above command will generate user_key (private key) and user_key.pub (public key) in the ~/.ssh directory.

Then, upload or copy the user’s public key, user_key.pub, to the CA server. Next, you can use the CA’s key user_ca to issue a user certificate for the user’s public key user_key.pub.

1
$ ssh-keygen -s user_ca -I user@example.com -n user -V +1d user_key.pub

The above command generates the user certificate user_key-cert.pub (the name of the user’s public key plus the suffix -cert). The meaning of each parameter of this command is as follows.

  • -s : Specify the key used by the CA to issue the certificate.
  • -I : The identity string, which can be set as a comment to distinguish the certificate, and can be used to revoke the certificate in the future.
  • -n user : Specify the user name, indicating that the certificate is valid only for that user name. If there are multiple user names, use comma to separate them. When a user logs in to the server with this user name, SSH uses this value to distinguish which certificate should be used to prove their identity and issued to the server.
  • -V +1d : Specify the validity of the certificate, in this case 1 day, to force the user to apply for a certificate once a day to improve security. By default, the certificate is valid forever.
  • -user_key.pub : The user’s public key.

After generating the certificate, you can use the following command to view the details of the certificate.

1
$ ssh-keygen -L -f user_key-cert.pub

Finally, set permissions for the certificate.

1
$ chmod 600 user_key-cert.pub

Server Installation Certificate

After the CA generates the server certificate ssh_host_rsa_key-cert.pub, you need to send the certificate back to the server, you can use the following scp command to copy the certificate over.

1
$ scp ~/.ssh/ssh_host_rsa_key-cert.pub root@host.example.com:/etc/ssh/

Then, add the following line to the server configuration file /etc/ssh/sshd_config .

1
HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub

上面的代码告诉 sshd 服务器证书是哪个文件。

重新启动 sshd。

1
2
3
$ sudo systemctl restart sshd
# or
$ sudo service sshd restart

Server Installation CA Public Key

In order for the server to trust the user certificate, you must copy the public key user_ca.pub , which is used by the CA to issue the user certificate, to the server.

1
$ scp ~/.ssh/user_ca.pub root@host.example.com:/etc/ssh/

The above command copies the public key user_ca.pub, which is used by the CA to issue user certificates, to the /etc/ssh directory of the SSH server.

Then, add the following line to the server configuration file /etc/ssh/sshd_config.

1
TrustedUserCAKeys /etc/ssh/user_ca.pub

The above approach is to add user_ca.pub to /etc/ssh/sshd_config, which will have the global effect that all accounts on the server will trust all user certificates issued by user_ca.

Another approach is to add user_ca.pub to the ~/.ssh/authorized_keys file of an account on the server and only have that account trust user certificates issued by user_ca. To do this, open ~/.ssh/authorized_keys, add a line starting with @cert-authority principals="..." and then add the contents of user_ca.pub, which looks like the following.

1
@cert-authority principals="user" ssh-rsa AAAAB3Nz...XNRM1EX2gQ==

In the above code, principals="user" specifies the name of the server account to which the user is logged in, which is usually the account where the authorized_keys file is located.

Restart sshd.

1
2
3
4

$ sudo systemctl restart sshd
# or
$ sudo service sshd restart

At this point, the SSH server has been configured to trust the certificate issued by user_ca.

Client installation certificate

Installing the user certificate on the client side is simple, just copy the user certificate user_key-cert.pub from the CA to the client and save it in the same directory as the user key user_key.

Client installation of CA public key

In order for the client to trust the server certificate, the public key host_ca.pub that the CA issues the server certificate with must be added to the client’s /etc/ssh/ssh_known_hosts file (global level) or ~/.ssh/known_hosts file (user level).

To do this, open the ssh_known_hosts or known_hosts file, append a line starting with @cert-authority *.example.com, and paste the contents of the host_ca.pub file (i.e., the public key) after it, which looks something like this.

1
@cert-authority *.example.com ssh-rsa AAAAB3Nz...XNRM1EX2gQ==

In the above code, *.example.com is a pattern match for the domain name, which means that as long as the server matches the pattern domain name and the CA issuing the server certificate matches the public key given later, it can be trusted. If there is no domain restriction, you can write * here. If there is more than one domain name pattern, you can use a comma to separate them; if the server does not have a domain name, you can use the host name (e.g. host1,host2,host3) or IP address (e.g. 11.12.13.14,21.22.23.24).

Then, you can use the certificate to log in to the remote server.

1
$ ssh -i ~/.ssh/user_key user@host.example.com

The -i parameter of the above command is used to specify the user’s key. If the certificate is in the same directory as the key, the certificate will be used automatically when connecting to the server.

Certificate of Revocation

The operation of revoking a certificate is divided into two types: revocation of user certificate and revocation of server certificate.

To revoke a server certificate, the user needs to modify or delete the line corresponding to the @cert-authority command in the known_hosts file.

For user certificate revocation, you need to create a new /etc/ssh/revoked_keys file in the server, and then add a line to the configuration file sshd_config with the following content.

1
RevokedKeys /etc/ssh/revoked_keys

The revoked_keys file holds the public keys of users that are no longer trusted and is generated by the following command.

1
$ ssh-keygen -kf /etc/ssh/revoked_keys -z 1 ~/.ssh/user1_key.pub

In the above command, the -z parameter is used to specify which line of the revoked_keys file the user’s public key is stored in, in this case it is stored in line 1.

If you need to revoke other user public keys later, you can use the following command to save them on line 2.

1
$ ssh-keygen -ukf /etc/ssh/revoked_keys -z 2 ~/.ssh/user2_key.pub

Reference https://www.ruanyifeng.com/blog/2020/07/ssh-certificate.html