Whenever I'm connecting to a new remote server via SSH, I tend to verify the fingerprint to make sure that I'm actually connecting to my own machine. Usually it's not that big a deal as I'm simply comparing two strings, but what if those two strings are created with two different hashing algorithms?
This is what I saw today when I connected to a new server for the first time.
notebook $ ssh remoteserver.name
The authenticity of host 'remoteserver.name' can't be established.
ECDSA key fingerprint is SHA256:2weq/LEmJ77j6sJUV6krRPnA9KUqgoojH+uM0hOcOJY.
Are you sure you want to continue connecting (yes/no)?
Ok, instead of just typing yes
, let's verify that real quick. To do that, I ssh'd into the hypervisor and connected to the server via direct console.
Now there are three ways I know of, how to verify the key, all of which boil down to string comparison. The question is, how to generate the string.
The easiest way is to ssh into localhost
server $ ssh localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ECDSA key fingerprint is 9b:1f:c9:df:e6:58:59:45:5d:5b:c0:3a:e4:e0:11:9c.
Are you sure you want to continue connecting (yes/no)?
Shoot, that's a problem. My notebook generated an SHA256+Base64
fingerprint, which is the default nowadays, while the ssh client on the server (all versions prior to 6.8) uses the old MD5 algorithm.
The reason for this is the difference in the ssh-client versions.
notebook $ ssh -V
OpenSSH_6.9p1 Ubuntu-2, OpenSSL 1.0.2d 9 Jul 2015
server $ ssh -V
OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.3, OpenSSL 1.0.1f 6 Jan 2014
Both machines have all updates installed, so the versions are up to date on their respective distros. One way to bypass this is by generating the fingerprint with ssh-keygen
server $ ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key
256 9b:1f:c9:df:e6:58:59:45:5d:5b:c0:3a:e4:e0:11:9c root@remoteserver.name (ECDSA)
Same result, let's try specifying the FingerprintHash
option, as suggested in this book.
server $ ssh -o FingerprintHash=sha256 localhost
command-line: line 0: Bad configuration option: fingerprinthash
Hm, the ssh client version on the server doesn't seem to support it. How about the -E
option for ssh-keygen
?
$ ssh-keygen -E sha256 -lf /etc/ssh/ssh_host_ecdsa_key.pub
unknown option -- E
Ok, so that didn't work either, not even on my notebook. Luckily there is a way to generate the key fingerprint manually.
server $ awk '{print $2}' /etc/ssh/ssh_host_ecdsa_key.pub | base64 -d | sha256sum -b | sed 's/ .*$//' | xxd -r -p | base64
2weq/LEmJ77j6sJUV6krRPnA9KUqgoojH+uM0hOcOJY=
notebook $ ssh remoteserver.name
ECDSA key fingerprint is SHA256:2weq/LEmJ77j6sJUV6krRPnA9KUqgoojH+uM0hOcOJY.
Looks like the same, however that's not really a convenient way to do things. There is one other way I can think of. Remember the FingerprintHash function I tried earlier? We can use it on the newer client to downgrade the fingerprinting to md5 and compare that with the servers key-gen
result.
notebook $ ssh -o FingerprintHash=md5 remoteserver.name
ECDSA key fingerprint is MD5:9b:1f:c9:df:e6:58:59:45:5d:5b:c0:3a:e4:e0:11:9c.
server $ ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub
256 9b:1f:c9:df:e6:58:59:45:5d:5b:c0:3a:e4:e0:11:9c root@remoteserver.name (ECDSA)
That's more like it, even though I'd prefer to use the newer SHA256+base64. If you don't want to compare strings character by character, then you might like the following alternative way.
$ ssh-keyscan remoteserver.name
remoteserver.name ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD4T41P6Byl4Qj2d/pzTJbiYs6Ld23KiSbjjGnZ1VUCQaIKFRa1dYGbxHe7v5JKLnfzmkVdTDxwHfbZWIomOFs6qFCoCXU4XsNwiwfDKjy2MZYN0+OJ2lq5hGqCDv66X4vG8PGgx4Vf0/iGIsILSoib8rPdX0jcjgtu4IeaPDt/sqgc09mVJzwVKnp37rlSTGSz2tRvyAo9koIWB+DOTUtq3QGbeQvyaY8pJIapi4BmvMznTt2vtXo15G3MFrT3dA9HIurtE8uX9ohVXL52GhAMm35GSoIwGY5mvp3QbNdG15bm2Rwn/4689gC6dZ2lkb+puOMV5OTTfURsj3q9Mjdd
remoteserver.name ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBG51NabehVOdZ/5G18erFMrtV54OQ8T+R6dShAINsfQPI7cOVaGxTBiOGWojfQfnOOgY32UzBxosBu3vKtLfxnM=
remoteserver.name ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG/XXHwyejGBMxCqVyiWR6Z4KbwqOlj+p9SEuxrqXOkp
Copy the output into a file on the remote server and run the following command to generate a fingerprint image.
$ ssh-keygen -lvf remoteserver_keys.pub
2048 a9:8b:d6:46:cd:44:7b:36:ba:b7:0a:4c:c4:6a:a7:75 remoteserver.name (RSA)
+--[ RSA 2048]----+
| |
| . . |
| o. . |
| o o.+ |
| o ++E+ . |
| . *.o+ |
| .o+ . |
| ..oo. . |
| .... .o.. |
+-----------------+
256 9b:1f:c9:df:e6:58:59:45:5d:5b:c0:3a:e4:e0:11:9c remoteserver.name (ECDSA)
+--[ECDSA 256]---+
| ..o ...*|
| E . ..+|
| . = . ..|
| . + .|
| S . .|
| + . o |
| o + o |
| . o +. |
| . ooo |
+-----------------+
256 9e:a9:07:82:ad:4a:12:4b:b8:f6:fd:de:4a:05:80:d5 remoteserver.name (ED25519)
+--[ED25519 256--+
| oo. |
| . .E |
| . |
|. . |
|o. o S. |
|.+. o ...o |
|+o . . o+ |
|+ o . ..o |
|.. . .+=.. |
+-----------------+
Then run the same key-gen
command on the servers public key and compare the result with the images above. One should match.
$ ssh-keygen -lvf /etc/ssh/ssh_host_ecdsa_key.pub
256 9b:1f:c9:df:e6:58:59:45:5d:5b:c0:3a:e4:e0:11:9c root@remoteserver.name (ECDSA)
+--[ECDSA 256]---+
| ..o ...*|
| E . ..+|
| . = . ..|
| . + .|
| S . .|
| + . o |
| o + o |
| . o +. |
| . ooo |
+-----------------+
While this is more work than the -o FingerprintHash=md5
solution, it's a bit easier to compare the results.