Einführung

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:

$ m m o o s t t s d d h . . - c c k h h e . . y g I I e N N n S S - S S r H H F F m P P o t 1 2 d . 1 1 c h 5 6 . 9 9 8 1 e 7 0 4 8 e a 7 d 2 b 0 f 5 d 9 e 8 e 8 8 7 3 5 1 7 2 0 1 2 b 1 b b 4 5 e 4 6 6 4 b 6 7 f 0 a 3 4 4 8 2 7 2 3 0 5 0 7 f 4 8 2 4 4 6 3 5 a 6 8 0 1 6

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:

#!/usr/bin/env bash

HOST="$1"

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

for i in /etc/ssh/ssh_host_*_key.pub
do
case "`cut -d_ -f3 <<< $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

Die aktuellste Version davon gibt es auf GitHub in meinem Scripts Repository: sshfpgen.

So generiert man alle SSHFP Records:

$ m m m m m m o o o o o o t t t t t t / d d d d d d s . . . . . . s c c c c c c h h h h h h h f . . . . . . p g I I I I I I e N N N N N N n S S S S S S m S S S S S S o H H H H H H t F F F F F F d P P P P P P . c 2 2 3 3 1 1 h . 1 2 1 2 1 2 6 d 6 c 5 c 9 6 3 2 9 b 1 b e c 8 f 7 6 b d e 1 4 a b c 0 6 e b 2 1 8 b 7 a 5 8 a a 2 9 f 5 d 4 0 5 2 7 b 4 5 e 5 7 f d 9 8 7 a d 5 8 9 e c e 3 8 b 0 2 e 1 7 9 e 0 8 2 5 b 9 7 3 2 7 1 1 7 1 4 0 1 f 3 2 d 2 7 b f 1 8 1 4 6 8 b a b 8 8 c b f 5 0 9 8 4 0 4 d 1 0 e c 6 f 3 1 6 a b b 2 5 4 4 7 4 b 4 6 9 0 9 4 5 f 4 3 5 f 2 a 4 4 d 6 f 4 0 2 9 9 f 8 e 2 6 a 1 7 0 0 1 f 8 3 5 0 c a b 5 8 f f 5 b 7 2 8 b 2 5 4 6 4 a 9 4 2 a 6 d d b 4 2 5 a d d 3 d 6 c d 7 a 7 0 3 8 d 8 e 6 e 5 a 1 2 f 1 a 8 7 a d a 6 c b 8 6 6 e f 6 1 d c 7 4 5 9 d f 1 8 5 3 d e 6 8 1 c 2 a b a 2 4 3 6 2 b 6 c 7 3 3 e 3 3 e 6 e 0 d 5 f e d 5 2 1 e 3 6 2 2 0

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).

$ ; ; ; ; ; ; ; ; m m m m m m ; ; ; ; ; ; o o o o o o d E t t t t t t i g G f O D A d d d d d d g l o l P N N . . . . . . o t > a T S S c c c c c c m b H g : W h h h h h h o D a a E s P E . . . . . . t i l n A : S v R d G s D E e . o w E q U r S 8 8 8 8 8 8 c 9 p e R r D s E 6 6 6 6 6 6 h . t r < O i C 4 4 4 4 4 4 9 i : < r S o T 0 0 0 0 0 0 s . o - d E n I 0 0 0 0 0 0 s 2 n C : O h - s o r T N I I I I I I f P : p a I 0 : N N N N N N p 2 c O , + o a N S S S S S S c d d : f S S S S S S + m e ; l H H H H H H n d : a F F F F F F o Q g P P P P P P s Q U s t m U E : 3 1 1 2 2 3 a o E R ; t t R Y 2 1 2 1 2 1 s d Y : u . , d C 5 C 6 D 6 + c 1 p 2 9 B 9 6 3 n h s , : C 8 F 1 B E o t D E 1 7 6 B a s a A 5 C 0 6 4 A B d s t N 1 1 8 B E B 2 d h u S 2 8 A A 7 A 5 i f s W 5 D 4 2 9 F t p : E 7 B 4 0 5 2 i R 7 F D 5 E 5 o + N : A D 5 9 8 7 n n O C E 3 8 9 E a o E 8 2 E 1 8 B 0 l s R , 0 8 2 7 9 E t R 7 3 2 5 B 9 + a O A 7 1 4 7 1 1 n t R U 3 2 D 0 1 F o s , T F 1 8 2 7 B a H 8 B A 1 4 6 u + i O C B F B 8 8 t n d R 8 4 0 5 0 9 h o : I 0 E C 4 D 1 o a T 1 6 A 6 F 3 r d 7 Y 5 4 4 B B 2 i d 9 : 4 6 9 7 4 B t i 1 5 F 4 0 9 4 y t 6 0 2 A 4 3 5 F i , F 4 0 4 D 6 + o F 8 E 2 9 9 n n A 1 7 0 2 6 A o a D 8 3 5 0 1 F q l D B 5 8 0 C A u I B 7 2 F F 5 e + T 5 4 6 8 B 2 s n I 4 2 A 4 A 9 t o O B 4 2 6 D D i a N D 3 D 5 A D o u A 7 A 7 6 C D n t L D 8 E 0 3 8 h : A 1 2 6 E 5 @ o 1 A F 8 r 1 7 A 8 . i A 6 D 8 t B 8 C . y 6 E 6 8 6 1 F . + C 7 D 8 n 5 9 4 o F 1 D ` q 5 3 8 u E 6 D ` e 1 C 8 s A B 2 t 2 4 A i 6 2 3 o 6 C B n 3 3 7 @ 3 3 E 8 6 E E . D 5 0 8 E D F . 2 1 5 8 3 6 E . 2 0 2 8

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 Verbindung aufbauen

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

$ T E M A W h C a r a s e D t e r s S c n h a A h y i u i o n m t k n u g o h e g : t e y s d n h u P . t f o r e c i i s e r h c n t m i g y a t e k o n y r e u e p y n o r w t f i f a l n i n y h t n t o g a s i e t d t s r o d p e ' 8 r c d m e i o o : n n ' t f t t m d f i o . : f n t c 0 o u d h 1 u e . : n c ( 3 d c h 5 5 o , . : i n 5 4 9 n n . 5 8 e 4 . : D c 5 1 8 N t . 0 8 S i 1 5 : . n 0 . 5 g 5 7 6 . 1 : ( 7 ) f y 1 ' 7 e ' : s c 1 / ( a f n E n : o C ' 7 ) D t a ? S : A b 1 y ) e 1 e : s t e 2 o s 8 t : t a 8 h b 6 e l : i e l s 4 i h : s e 3 t d 4 . : o 1 f 1 . k n o w n h o s t s .

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:

$ @ @ @ I S I T 8 P U T E N A @ @ T o t h e l p h C o r s @ @ m e : e d e D e s @ @ I e i f a a S m h @ @ S o s f f s t a A a y @ W @ n i : e e u t o m @ A @ P e a n 0 t k c u o @ R @ O l g 1 c t h e h t @ N @ S c s e : o h e y i s d @ I @ S o o r 3 n e n n u . @ N @ I u p 5 t t f g r c @ G @ B l p r : a S i i e h @ : @ L d o i 9 c S c n h @ @ E s n 8 t H i g o y @ R @ b s t : F t e s o @ E @ T e i 8 y P y r t u @ M @ H b f 8 o p @ O @ A e l o : u R o r k w @ T @ T a e r 5 r R f i e a @ E @ v 6 n y n @ @ S e t t : s i h t t @ H @ O s h h f y n o f @ O @ M d a e 7 s s i i t @ S @ E r t : t D t s n o @ T @ O o E 1 e N g @ @ N p a C f m S ' 8 e c @ I @ E p D : m e r o @ D @ i h S 7 a w o : p n @ E @ I n o A a d i t f r t @ N @ S g s : m t d f i i @ T @ t k 1 i h . : n n @ I @ D o e 1 n c 0 t u @ F @ O n k y : i t h 1 e @ I @ I e 2 s h : f @ C @ N y y s 8 t e ( 3 o c @ A @ G o e : r 5 5 u o @ T @ u h n 8 a n . : n n @ I @ S a t 6 t e 4 9 d n @ O @ O r s : o w 5 8 e @ N @ M i b e r . : i c @ @ E g j y 4 . h 1 8 n t @ H @ T h u : o 0 8 i @ A @ H t s t 3 s 5 : D n @ S @ I t h 4 t . 5 N g @ @ N n e : 7 6 S @ C @ G o b 1 k 1 : . ( @ H @ w e r 1 e ) f y @ A @ N e e . y ' 7 e @ N @ A ( n m : s @ G @ S m o t c 1 / @ E @ T a c t o a f n @ D @ Y n h e n : o @ ! @ ! - a g ' 7 ) @ @ i n h e t a ? @ @ n g o t : @ @ - e s b 1 @ @ t d t r e 1 @ @ h . i : @ @ @ e i d e 2 - s s 8 m o t : i f a 8 d b 6 d t l : l h i e e i s 4 s h : a e 3 t m d 4 t e . : a s 1 c s 1 k a . ) g ! e .