ssh certificates part 2
This is the second part of the SSH certificate series, server side SSH certificates. You can find the first one here.
This post shows, what use server side certificates can be and how they can be created.
What use have server side certificates?
SSH certificates on the host side are used to extend the ssh host keys. These can be used to better identify a running system, as multiple names can be provided in the certificate. This avoids the message of a wrong host key in a shared IP system, as all IPs and names can be provided.
SSH certificates can also help to identify freshly deployed systems in that the system gets certified directly after the deployment by a build ca.
signing a host key
For this step, we need a CA key. How that can be generated was mentioned in the first part. We also need the host public key to sign. This can be either copied from /etc/ssh/ from the server or it can be fetch using ssh-keyscan.
ssh-keyscan foo.example.org
It can also take a parameter for a specific type
ssh-keyscan -t ed25519 foo.example.org
This is needed for some older versions of openssh, where ed25519 public keys were not fetched by default with ssh-keyscan.
The output returned looks like the following:
zero-knowledge.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPIP0JSsdP2pjtcYNcmqyPg6nLbMOjDbRf0YR/M2pu2N
The second and third field need to be put into a file, so that it can be used to generate the certificate.
A complete command would then look like this:
ssh-keyscan foo.example.org | awk '/ssh|ecdsa/ { print $2,$3 }' > host.pub
With the resulting file, we can now proceed to create the certificate.
ssh-keygen \
-s ca.key \
-V '+52w1d' \
-I 'foohost' \
-h \
-n foo.example.org,bar.example.org \
host.pub
The meaning of the options is:
-s
the key to use for signing (the ca)-V
interval the certificate is valid-I
the identity of the certificate (a name for the certificate)-h
flag to create a host certificate-n
all names the host is allowed to use (This list can also contain IPs)
The last option is the public key file to certify.
This results in a file host-cert.pub, which contains the certificate. It can be viewed like the SSH client certificate, with ssh-keygen.
ssh-keygen -L -f host-cert.pub
This file now has to be placed in the same directory like the public key on that
host, with the same -cert.pub
ending.
The last step on the server is to adjust the _sshdconfig, so that it includes the certificate. For that, add the following line for the fitting host key, for example:
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
With a reload, it should load the certificate and make it available for authentication.
Now the only thing left to do is to tell the client, that it should trust the
CA to identify systems. For that, the public key of the CA has to be added
to the file ~/.ssh/known_hosts
in the following format
@cert-authority * <content of ca.pub>
The * marks a filter, so different CAs can be trusted depending on the domain.
With this, you are able to connect to your server only using the certificate provided by the server. When connecting with debugging on, you should get output like the following:
$ ssh -v foo.example.com
...
debug1: Server host key: ssh-ed25519-cert-v01@openssh.com SHA256:+JfUty0G4i3zkWdPiFzbHZS/64S7C+NbOpPAKJwjyUs
debug1: Host 'foo.example.com' is known and matches the ED25519-CERT host certificate.
debug1: Found CA key in /home/foo/.ssh/known_hosts:1
...
With the first part and now the second part done, you can already lock up your infrastructure pretty fine. In the next part, I will show some stuff I use to keep my infrastructure easily managable.