More secure SSH connectivity with DNSSEC


Everyone who uses SSH knows that the first time they connect to the server, a message appears confirming the fingerprint of the key. Further, the key is stored on the client side, and this message is not displayed again until the saved key is changed. But what is the practical meaning of this procedure?

In real life, almost no one checks the fingerprint of the server’s SSH key without really thinking about the possibility of MiTM attacks. With the advent of the SSHFP DNS record, the server key fingerprint can be stored in DNS and authenticated using DNSSEC. In this case, you do not even need to confirm the key at the first connection. This article will show you how to configure an SSHFP record for your SSH server.

Test server


First, we need a server. In the RuVDS panel, the details for SSH access are located immediately on the server card. We save the IP address and password for the connection.



You can also configure the firewall directly from the control panel to allow SSH access only for your IP.

To configure SSHFP, a domain must be directed to the server’s IP address; we will configure DNS records for this domain.

How keys work in SSH


In the examples, we will consider only the OpenSSH package, since this is the most popular option.

When installing a new server, random SSH keys are generated, usually this happens immediately when installing the OpenSSH package or during the first boot if ready-made system images are used.

Key files are located here:

$ ls -la /etc/ssh/ssh_host_*_key*

/etc/ssh/ssh_host_dsa_key
/etc/ssh/ssh_host_dsa_key.pub
/etc/ssh/ssh_host_ecdsa_key
/etc/ssh/ssh_host_ecdsa_key.pub
/etc/ssh/ssh_host_ed25519_key
/etc/ssh/ssh_host_ed25519_key.pub
/etc/ssh/ssh_host_rsa_key
/etc/ssh/ssh_host_rsa_key.pub

In this list there are several keys of different types at once: dsa, rsa, ecdsa, ed25519. This is done for compatibility with different SSH clients. At the connection stage, the client and server agree on which key algorithm will be used. The client may ask the server to use a different algorithm if the proposed one is not supported. The server sends the public part of its key to the client and the user is prompted to check his fingerprint manually.


The server sends the fingerprint of the public key to the client at the time of connection.

If this is the first connection, a message will be displayed to the client with the request to manually verify the fingerprint:

The authenticity of host 'example.com (123.45.67.89)' can't be established.
ECDSA key fingerprint is SHA256:7Q4nIqjuo/lSXWFkt9RaJYVHrT6LUAc6KWrdQ4/DDeA.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

At this stage, we all usually click Yes without hesitation and the fingerprint of the key is saved to a file ~/.ssh/known_hosts. Now, if the key on the server changes, the client will be shown a message about a possible MiTM attack. It is assumed that for the very first time, the client performed a key check on their own and made sure of its authenticity.

This approach is quite risky, because if the attacker managed to seize the moment of the first connection, he will be able to slip his key and intercept the connection. In the case of c HTTPS, we have a third party that confirms the server key with a certificate. If the same approach as in SSH was used on the web, we would be constantly tormented by key verification messages and MiTM attacks would be everywhere, because no one would check the keys, but would simply always agree.

We store a key print in DNS. What are SSHFP entries


How to find out that the SSH key proposed by the server is really real and this is not a MiTM attack? Indeed, in order to enter the server and verify the key, you must first enter the password. But then the attacker will be able to instantly hack the server and replace all the data on it, so much so that we will not notice the catch. Therefore, we need a way to verify the authenticity of the key BEFORE the real connection.

For a long time, the only way to check the server’s SSH key before connecting was to use a different channel, for example, ask the server administrator to provide the server key fingerprint. This is inconvenient, so it’s easier to ignore the problem and always agree without hesitation.


SSHFP allows server key authentication before connecting through SSHFP DNS

- type of DNS records for storing SSH keys. The fingerprint of the SSH key is placed in the DNS server like a TXT record and signed with the DNSSEC key. That is, the first time you connect to the server using the host name, the client will be able to know the fingerprint of the server key through DNS in advance, and if it matches the proposed server, then connect without warning .

Configure DNSSEC


To use SSHFP, you need a domain name with DNSSEC configured. There are many public DNS services that offer a DNS control panel right away with the DNSSEC function. The most popular such service is CloudFlare. Consider the configuration using his example. For the following steps, the domain must be delegated to the Cloudflare NS server.

â–ŤStep 1 - generate a key


Go to the DNS panel -> Enable DNSSEC.

At this point, keys will be generated to sign your domain zone. You will be shown the public keys. They will need to be added on the side of the domain registrar.

â–ŤStep 2 - adding public keys to the registrar


Next, you need to create DS records containing the public key from the domain registrar.
Depending on your registrar, the DNSSEC key-adding interface may look different. It’s important not to confuse the values, as they can be named differently and differ from the names shown in CloudFlare.

The example below shows how the values ​​shown in the CloudFlare panel relate to the values ​​in the domain control panel of the Uniregistry registrar.



â–ŤStep 3 - check added DS records


After adding DS-records on the side of the registrar, you can check the settings are correct. On the CloudFlare side, the signing of DNS records will be activated only when the verification of the correctness of adding DS records on the side of the registrar is passed.


Waiting for the addition of DS records

After a couple of minutes or hours, if the records were added correctly, you will see such a message. This means that DNS responses are now signed using DNSSEC.



â–ŤStep 4 - verify DNSSEC operation


Now you can test the operation of DNSSEC on our domain using online services like dnssec-analyzer.verisignlabs.com . All checkmarks should be green.


DNSSEC Validation Result

Adding SSHFP Entries


We will generate SSHFP records on the server. In our example, we are administering a server with the address myserver.com . For this domain name, we previously configured DNSSEC.

On the server, execute the command:

#   SSHFP   SSH-
sudo ssh-keygen -r myserver.com

myserver.com IN SSHFP 1 1 057ecce168ace29d5a0099e3b63df2850e4c8e20
myserver.com IN SSHFP 1 2 52cd6099a304b9b8f57f2cd914e96a1b7477eb2f88c98c602
myserver.com IN SSHFP 2 1 42d677482e4450ee515d3aac94d96302a99bd4ec
myserver.com IN SSHFP 2 2 edda5fa445dc0da570c772a6df0d4012037e1a102840d29c4
...

Fingerprints will be generated for all keys from the / etc / ssh / folder . You can selectively generate fingerprints for specific keys by specifying the file path.

Now all these records need to be added in the DNS panel, in our case Cloudflare.


Adding an SSHFP record to the Cloudflare panel

So, you need to add all the keys obtained in the previous step. Now you can verify that the keys are added:

dig SSHFP myserver.com

In the answer you should see all the keys added. It may take time to sign new entries, so the keys in the response may not appear immediately. This usually does not take longer than 10-15 minutes.

Connect to the server


In order for the SSH client to verify the validity of the keys through DNS, you need to add enable this in the settings. The client config is located in the user's home folder. Add one line there.

#  
vi ~/.ssh/config

VerifyHostKeyDNS yes

Now you can connect to the server. For the purity of the experiment, you can remove the line with the fingerprint from ~ / .ssh / known_hosts . For clarity, you can add the -v option

#   
ssh -v root@myserver.com


# DNS  ,  SSHFP 
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
.....
DNS lookup error: data does not exist

# DNS  ,   
#    DNSSEC
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
....
debug1: found 8 insecure fingerprints in DNS
debug1: matching host key fingerprint found in DNS


# DNS  ,    DNSSEC
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
....
debug1: found 8 secure fingerprints in DNS
debug1: matching host key fingerprint found in DNS
debug1: ssh_rsa_verify: signature correct

If everything is configured correctly, then the first time you connect to the server, you will not be asked to manually verify the fingerprint of the key. This also requires the system DNS resolver to support DNSSEC validation.

It is important to remember that SSHFP will only work when connected to a server by domain name and will not work when connected by IP or another domain that does not have SSHFP records.


All Articles