SSH Fingerprints im DNS hinterlegen (SSHFP Record)

Verbindet man sich zum ersten Mal per SSH mit einem Server, sieht man den Fingerabdruck des Servers. Diesen sollte man im Idealfall vergleichen und erst mit yes bestätigen, wenn man sich sicher ist, dass es sich um den richtigen Fingerprint handelt. Stimmt der Fingerabdruck nicht, könnte man Opfer einer Man in the Middle Attacke sein. Das Vergleichen der Fingerprints ist etwas mühsam und mittels fuzzying (beispielsweise mit dem Tool ffp) können sehr ähnliche Fingerprints erstellt werden, welche dem Menschen auf den ersten Blick gleich erscheinen. Man kann sich einfach vor gefälschten SSH Fingerprints schützen, indem man diese in einem DNSSEC signierten speziellen DNS Record hinterlegt. Hierfür gibt es den speziellen SSHFP Record.

Wofür brauche ich den SSHFP Record?

Verbindet man sich zum ersten Mal per SSH mit einem Server, sieht man den Fingerabdruck des Servers. Diesen kann man mit yes bestätigen und damit in die Datei ~/.ssh/known_hosts eintragen. Hat sich der Fingerabdruck bei einem erneuten Verbinden verändert, bekommt man eine Warnung. Ist es der selbe, ist alles OK und der Verbindungsaufbau geht weiter.

Damit der Finerprint nicht von Hand verglichen werden muss, kann man diesen in einem speziellen DNS Record hinterlegen. Dieser DNS Record heisst SSHFP und wurde im RFC 4155 spezifiziert und im RFC 6594 erweitert.

Automatisches erstellen des SSHFP Records

Den SSHFP Record kann man sich direkt mit ssh-keygen generieren lassen. Hier ein Beispiel für den Host motd.ch:

$ ssh-keygen -r motd.ch.
motd.ch. IN SSHFP 1 1 598e08adbfdee83121bb4e646fa4873574243a81
motd.ch. IN SSHFP 2 1 69174e7205988757021b546b70342200f8465606

Wichtig:

  • Dies muss auf dem Host ausgeführt werden, wessen SSHFP Record man erstellen will.
  • Man beachte den Punkt am Schluss des Hostsnamens. Dieser ist nötig, damit der Eintrag in der Zone stimmt. Ohne “Root Punkt” würde ein Eintrag für motd.ch.motd.ch. erstellt werden, da der Nameserver gegebenenfalls den Zonennamen bzw. $ORIGIN an den Hostnamen anhängt.

Aufbau des SSHFP Records

Die erste Zahl steht für den verwendeten Algorithmus:

  • 0: Reserviert
  • 1: RSA
  • 2: DSS
  • 3: ECDSA
  • 4: ED25519

Die zweite Zahl steht für den Fingerprint Typ:

  • 0: Reserviert
  • 1: SHA-1
  • 2: SHA-256

Diese Aufstellung ist auch bei der IANA abrufbar: DNS SSHFP Resource Record Parameters: https://www.iana.org/assignments/dns-sshfp-rr-parameters/dns-sshfp-rr-parameters.xhtml.

Händisches Erstellen des SSHFP Records

Ältere Versionen von ssh-keygen generieren keine Einträge für den ECDSA und den ED25519 Algorithmus. Diese muss man gegebenenfalls von Hand erstellen. Ich habe mir folgendes Script geschrieben, welches für alle verfügbaren Algorithmen und Fingerprint Typen alle SSHFP Records erstellt:

#!/bin/bash
<code lang="bash">

HOST=”$1″

<code lang="bash">

if (($# < 1)) then echo “Usage: sshfpgen ”
exit 1
fi

 
for i in /etc/ssh/ssh_host_*_key.pub
do
case "`cut -d_ -f3 &lt;&lt;&lt; $i`"
  in
    rsa)
      echo $HOST IN SSHFP 1 1 `cut -f2 -d ' '  $i | base64 -d | sha1sum  | cut -f 1 -d ' '`
      echo $HOST IN SSHFP 1 2 `cut -f2 -d ' '  $i | base64 -d | sha256sum  | cut -f 1 -d ' '`
    ;;
    dsa)
      echo $HOST IN SSHFP 2 1 `cut -f2 -d ' '  $i | base64 -d | sha1sum  | cut -f 1 -d ' '`
      echo $HOST IN SSHFP 2 2 `cut -f2 -d ' '  $i | base64 -d | sha256sum  | cut -f 1 -d ' '`
    ;;
    ecdsa)
      echo $HOST IN SSHFP 3 1 `cut -f2 -d ' '  $i | base64 -d | sha1sum  | cut -f 1 -d ' '`
      echo $HOST IN SSHFP 3 2 `cut -f2 -d ' '  $i | base64 -d | sha256sum  | cut -f 1 -d ' '`
    ;;
    ed25519)
      echo $HOST IN SSHFP 4 1 `cut -f2 -d ' '  $i | base64 -d | sha1sum  | cut -f 1 -d ' '`
      echo $HOST IN SSHFP 4 2 `cut -f2 -d ' '  $i | base64 -d | sha256sum  | cut -f 1 -d ' '`
    ;;
  esac
done

Das Skript gibt es auch in meinem Scripts Repository auf GitHub: https://github.com/emanuelduss/Scripts/blob/master/sshfpgen.

So generiert man alle SSHFP Records:

$ ./sshfpgen motd.ch.
motd.ch. IN SSHFP 2 1 69174e7205988757021b546b70342200f8465606
motd.ch. IN SSHFP 2 2 d6b6aba95e89b9b117480dfb495d961cfbadac3ef8dc6fd4d8d82a3b7ee0f5e2
motd.ch. IN SSHFP 3 1 63ebb25f257e0e91fb689132b4f69afa529ddd85
motd.ch. IN SSHFP 3 2 c2cdc18577ac20773f8c8015452ff18bb54bd7da17ab66c5f5e1a266336de232
motd.ch. IN SSHFP 1 1 598e08adbfdee83121bb4e646fa4873574243a81
motd.ch. IN SSHFP 1 2 cbf16ba44d531224d8af0ca49440e05826a2d7e2aa68e179136cb42c33e5d160

Wie man sieht sind jetzt einige Einträge (Neu ECDSA und zusätzlich alle mit SHA256) mehr erstellt worden. Diese kann man jetzt ins Zonenfile eintragen.

Eintragen ins Zonenfile

Dieser SSHFP Record trägt man jetzt in der DNS Zone ein, welche für diesen Hostnamen zuständig ist. Damit man der Antwort vom DNS Server auch trauen kann, sollte diese Zone auch mit DNSSEC signiert sein und der verwendete Resolver sollte die Antwort überprüfen (man beachte das ad Flag in der Ausgabe).

$ dig motd.ch sshfp  +nostats +noadditional +noauthority +noquestion @8.8.8.8
 
; &lt;&lt;&gt;&gt; DiG 9.9.2-P2 &lt;&lt;&gt;&gt; motd.ch sshfp +nostats +noadditional +noauthority +noquestion @8.8.8.8
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 7916
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 8, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; ANSWER SECTION:
motd.ch.        86400   IN  SSHFP   3 2 C2CDC18577AC20773F8C8015452FF18BB54BD7DA17AB66C5F5E1A266 336DE232
motd.ch.        86400   IN  SSHFP   1 1 598E08ADBFDEE83121BB4E646FA4873574243A81
motd.ch.        86400   IN  SSHFP   1 2 CBF16BA44D531224D8AF0CA49440E05826A2D7E2AA68E179136CB42C 33E5D160
motd.ch.        86400   IN  SSHFP   2 1 69174E7205988757021B546B70342200F8465606
motd.ch.        86400   IN  SSHFP   2 2 D6B6ABA95E89B9B117480DFB495D961CFBADAC3EF8DC6FD4D8D82A3B 7EE0F5E2
motd.ch.        86400   IN  SSHFP   3 1 63EBB25F257E0E91FB689132B4F69AFA529DDD85

SSH Client konfigurieren

Jetzt muss man dem SSH Client noch sagen, dass er die SSHFP Records zur Verifizierung verwenden soll. Dazu fügt man in der Datei /etc/ssh/ssh_config folgenden Eintrag ein:

VerifyHostKeyDNS ask

Durch die Option ask muss man weiterhin mit yes bestätigen, man bekommt jedoch den Hinweis, dass der Key mit dem SSHFP Record übereinstimmt.. Verwendet man yes statt ask wird der Key automatisch akzeptiert.

SSH Verbidung aufbauen

Folgendermassen sieht der Verbindungsaufbau aus, wenn man sich zum ersten Mal mit dem Server verbindet:

$ ssh motd.ch
The authenticity of host 'motd.ch (5.45.105.71)' can't be established.
ECDSA key fingerprint is 8e:ff:01:35:98:88:56:f7:1f:7a:11:28:86:e4:34:11.
Matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'motd.ch,5.45.105.71' (ECDSA) to the list of known hosts.

Yay! Man sieht die Zeile: “Matching host key fingerprint found in DNS.”. Der Public SSH Fingerprint stimmt also mit dem SSHFP Record überein.

Stimmt der SSHFP Record und der Fingerprint nicht überein, erscheint folgende Meldung:

$ ssh motd.ch
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
8e:ff:01:35:98:88:56:f7:1f:7a:11:28:86:e4:34:11.
Please contact your system administrator.
Update the SSHFP RR in DNS with the new host key to get rid of this message.
The authenticity of host 'motd.ch (5.45.105.71)' can't be established.
ECDSA key fingerprint is 8e:ff:01:35:98:88:56:f7:1f:7a:11:28:86:e4:34:11.
No matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?

Links und weitere Informationen

6 thoughts on “SSH Fingerprints im DNS hinterlegen (SSHFP Record)”

  1. Servus, besten Dank für die Infos. Etwas ist mir jedoch nicht klar: Was ist genau gemeint mit der Gültigkeit von:
    4: ED25519 (nur bis Mai 2015 gültig)

    Reply
  2. Kann es eventuell sein, dass du hier ein Negativbeispiel zeigst, wie es eben nicht aussehen darf, wenn man sich mit dem SSH-Server verbindet?

    Die Zeilen:
    Update the SSHFP RR in DNS with the new host key to get rid of this message.
    The authenticity of host ‘motd.ch (5.45.105.71)’ can’t be established.
    ECDSA key fingerprint is 8e:ff:01:35:98:88:56:f7:1f:7a:11:28:86:e4:34:11.
    No matching host key fingerprint found in DNS.

    Dürften ja schon das Meiste sagen.

    Grüße,
    Alex

    Reply
    • Hallo Alex

      Ich zeige ja beide Varianten:

      Zuerst wie es ist, wenn der SSHFP Record im DNS gefunden wird:

      $ ssh motd.ch
      The authenticity of host 'motd.ch (5.45.105.71)' can't be established.
      ECDSA key fingerprint is 8e:ff:01:35:98:88:56:f7:1f:7a:11:28:86:e4:34:11.
      Matching host key fingerprint found in DNS.
      Are you sure you want to continue connecting (yes/no)? yes
      Warning: Permanently added 'motd.ch,5.45.105.71' (ECDSA) to the list of known hosts.

      Und danach wenn er nicht gefunden wird, bzw. wenn er nicht übereinstimmt:

      $ ssh motd.ch
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
      Someone could be eavesdropping on you right now (man-in-the-middle attack)!
      It is also possible that a host key has just been changed.
      The fingerprint for the ECDSA key sent by the remote host is
      8e:ff:01:35:98:88:56:f7:1f:7a:11:28:86:e4:34:11.
      Please contact your system administrator.
      Update the SSHFP RR in DNS with the new host key to get rid of this message.
      The authenticity of host 'motd.ch (5.45.105.71)' can't be established.
      ECDSA key fingerprint is 8e:ff:01:35:98:88:56:f7:1f:7a:11:28:86:e4:34:11.
      No matching host key fingerprint found in DNS.
      Are you sure you want to continue connecting (yes/no)?

      Es wird also auch ein Positivbeispiel gegeben.

      Gruss,
      Emanuel

      Reply
  3. Danke für die Beschreibung.
    Kleiner Typo:
    > Aufbau des SSHFP Records
    > Die zweite Zahl steht für den Fingerprint Typ:
    muss
    2: SHA-256
    und nicht
    1: SHA-256
    lauten.

    Schöne Grüße vom Niederrhein
    –rudolf

    Reply

Leave a Reply to Alexander Jank Cancel reply