Holen Sie sich den Fingerabdruck des SSH-Server-Schlüssels

82

Gibt es eine Möglichkeit , einen SSH-Serverschlüssel-Fingerabdruck programmgesteuert abzurufen, ohne sich bei ihm zu authentifizieren ?

Ich versuche es ssh -v user@host false 2>&1 | grep "Server host key", aber dies hängt und wartet auf ein Passwort, wenn keine schlüsselbasierte Authentifizierung eingerichtet ist.

Goncalopp
quelle

Antworten:

71

Sie können dies tun durch die Kombination ssh-keyscanund ssh-keygen:

$ file=$(mktemp)
$ ssh-keyscan host > $file 2> /dev/null
$ ssh-keygen -l -f $file
521 de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef host (ECDSA)
4096 8b:ad:f0:0d:8b:ad:f0:0d:8b:ad:f0:0d:8b:ad:f0:0d host (RSA)
$ rm $file

(leider geht das viel einfacher ssh-keyscan host | ssh-keygen -l -f /dev/stdinnicht)

Andreas Wiese
quelle
1
Aber vielleicht ssh-keygen -l -f - <(ssh-keyscan host)doch?
ein Lebenslauf
21
OpenSSH> = 7.2 ssh-keyscan kann von stdin lesen:ssh-keyscan host | ssh-keygen -lf -
mykhal
1
Tun Sie einfach:ssh-keygen -l -f <(ssh-keyscan host)
Christopher
1
Das ist ein ziemlich schlechter Ausdruck für Shell-Skripte, da es von einer Shell abhängt, die dies unterstützt, was die POSIX-Shell nicht tut.
Andreas Wiese
2
ssh-keygen -l -f -funktioniert wie erwartet in ssh-keygen 7.2 und höher. Es werden einige Kommentarzeilen zu STDERR erstellt, die herausgefiltert werden können, wie in der Antwort von Anthony Geoghegan oderssh-keyscan host 2>/dev/null | ssh-keygen -l -f -
Cedric Knight vom
56

Ich musste dies vor kurzem selbst tun, daher dachte ich, ich würde eine Antwort hinzufügen, die zeigt, wie dies (mit Versionen von OpenSSH 7.2 oder neuer ) in einer Zeile unter Verwendung der Prozessersetzung getan werden kann:

ssh-keygen -lf <(ssh-keyscan hostname 2>/dev/null)

Der folgende Text erläutert die Funktionsweise dieser Befehle und hebt einige Unterschiede im Verhalten älterer und neuerer Versionen der OpenSSH-Dienstprogramme hervor.

Holen Sie sich öffentliche Host-Schlüssel

Der ssh-keyscanBefehl wurde entwickelt, damit Benutzer öffentliche Hostschlüssel erhalten können, ohne sich beim SSH-Server authentifizieren zu müssen. Von seiner Manpage:

ssh-keyscanist ein Dienstprogramm zum Erfassen der öffentlichen SSH-Hostschlüssel einer Reihe von Hosts. Es wurde entwickelt, um beim Erstellen und Überprüfen von ssh_known_hostsDateien zu helfen .

Schlüsselart

Die Art des abzurufenden Schlüssels wird mit der -tOption festgelegt.

  • rsa1 (veraltetes SSH-Protokoll Version 1)
  • rsa
  • dsa
  • ecdsa (neueste Versionen von OpenSSH)
  • ed25519 (neueste Versionen von OpenSSH)

In modernen OpenSSH-Releases müssen standardmäßig die Schlüsseltypen rsa (seit Version 5.1), ecdsa(seit Version 6.0) und ed25519(seit Version 6.7) abgerufen werden .

In älteren Versionen von ssh-keyscan(vor OpenSSH Version 5.1) war der Standardschlüsseltyp veraltet rsa1(SSH-Protokoll 1), sodass die Schlüsseltypen explizit angegeben werden müssten:

ssh-keyscan -t rsa,dsa hostname

Holen Sie sich Fingerabdruck-Hashes von Base64-Schlüsseln

ssh-keyscandruckt den Host-Schlüssel des SSH-Servers im Base64-codierten Format. Um dies in einen Fingerabdruck-Hash umzuwandeln, kann das ssh-keygenDienstprogramm mit seiner -lOption verwendet werden, um den Fingerabdruck des angegebenen öffentlichen Schlüssels zu drucken.

Bei Verwendung von Bash, Zsh (oder der Korn-Shell) kann die Prozessersetzung für einen praktischen Einzeiler verwendet werden:

ssh-keygen -lf <(ssh-keyscan hostname 2>/dev/null)

Hinweis : In OpenSSH-Versionen vor 7.2 haben die ssh-keygenzum Lesen von Dateien verwendeten Funktionen Named Pipes (FIFOs) nicht sehr gut verarbeitet, sodass diese Methode nicht funktioniert und die Verwendung temporärer Dateien erforderlich ist.

Hashing-Algorithmen

Aktuelle Versionen von SHA256 Fingerabdruck-Hashes der Tasten ssh-keygendrucken . Um MD5- Hashes der Serverschlüssel-Fingerabdrücke abzurufen (das alte Verhalten), kann die Option verwendet werden, um den Hash-Algorithmus anzugeben:-E

ssh-keygen -E md5 -lf <(ssh-keyscan hostname 2>/dev/null)

Pipeline verwenden

Wenn Sie eine POSIX-Shell (z. B. dash) ohne Prozessersetzung verwenden, funktionieren die anderen Lösungen mit temporären Dateien. In neueren Versionen von OpenSSH (seit 7.2) kann jedoch eine einfache Pipeline verwendet werden, da ssh-keygensie -als Dateinamen für den Standardeingabestream akzeptiert und einen einzeiligen Pipelinebefehl zulässt.

ssh-keyscan hostname 2>/dev/null | ssh-keygen -E md5 -lf -
Anthony Geoghegan
quelle
Schöne und gründliche Antwort, das ist sicherlich besser als eine temporäre Datei zu haben! Darf ich vorschlagen, dass Sie zu Beginn der Prozessersetzungsversion einen TL; DR angeben, damit ungeduldige Leute ihn schneller finden? :)
Goncalopp
3
Scheint auf Ubuntu 14.04 LTS nicht zu funktionieren; Ich erhalte die Fehlermeldung "/ dev / fd / 63 ist keine öffentliche Schlüsseldatei". Der Unterprozess funktioniert.
Melle
@melleb Ich habe dasselbe auf einem 12.04-System gefunden, auf das ich Zugriff habe. Ich vermute, dass ssh-keygenvon älteren Versionen von OpenSSH ein Problem beim Lesen aus dem FIFO / Named Pipe vorliegt. Ich werde das untersuchen (und meine Antwort aktualisieren), wenn ich etwas Freizeit habe.
Anthony Geoghegan
3
@melleb Nachdem ich viel Zeit mit dem Herunterladen verschiedener Quellcode-Releases und dem Einfügen von Debugging- printfAnweisungen in die do_fingerprint()Funktion verbracht hatte, stellte ich fest, dass mit OpenSSH-Versionen vor 7.2 die ssh-keygenzum Lesen von Dateien verwendeten Funktionen Named Pipes (FIFOs) nicht so gut handhabten Die Prozessersetzungsmethode würde nicht funktionieren.
Anthony Geoghegan
Dies funktioniert. Wenn Sie es jedoch zur Überprüfung eines Fingerabdrucks verwenden, sollten Sie sich darüber im Klaren sein, dass eine Race-Bedingung vorliegt: Der Fingerabdruck, den Sie mit diesem Befehl überprüfen, entspricht nicht unbedingt dem des Schlüssels, den Sie abrufen, es sei denn, Sie geben den Schlüssel ab, bevor Sie ssh- aufrufen. keygen drauf.
CodeGnome
20

nmapBietet diese Möglichkeit mithilfe des ssh-hostkeySkripts.

So geben Sie den hexadezimalen Fingerabdruck des Schlüssels zurück:

$ nmap [SERVER] --script ssh-hostkey

So geben Sie den Inhalt des Schlüssels zurück:

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey=full

Zum Zurückkehren der visuellen Blase des Schlüssels

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey='visual bubble'

So geben Sie alle oben genannten Informationen zurück:

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey=all

Quelle: nmap docs

Bach
quelle
3
Gehen diese Beispiele davon aus, dass SSH immer auf Port 22 ausgeführt wird? Was ist, wenn ssh auf einem nicht standardmäßigen Port lauscht?
Martin Vegter
3
@MartinVegter (paraphrasiert Guarin42, der nicht kommentieren konnte :) nmap hat die -pOption, einen Port anzugeben, z -p 22000. Es ist auch möglich, die -vvOption zu verwenden, um die Ausführlichkeit (Menge der angegebenen Informationen) zu erhöhen
goncalopp
2

filezilla zeigt mit md5 gehashte Schlüssel im Hexadezimalformat an .

Verwenden Sie diesen Befehl , um dies auf Ihrem Ubuntu-Linux- Computer zu finden :

ssh-keygen -l -E md5 -f <(ssh-keyscan localhost 2>/dev/null)

Hinweis: Ersetzen Sie "localhost" durch die IP-Adresse des Computers, den Sie überprüfen möchten.

Cameron
quelle
1

Hier ist ein Shell-Skript (hauptsächlich Bourne-Shell, aber mit localSchlüsselwörtern, die in den meisten modernen /bin/shVersionen verfügbar sind ), das ich dazu geschrieben habe. Benutze es wie ssh-hostkey hostname. Es werden sowohl die Fingerabdrücke im sha256- als auch im md5-Format für alle Hostschlüssel für den angegebenen Hostnamen oder die angegebene IP-Adresse angezeigt. Sie können auch manuell " md5" oder " sha256" als zweites Argument angeben, um nur dieses bestimmte Format anzuzeigen.

Anstelle von Piping wird eine temporäre Datei verwendet, um die Kompatibilität mit älteren OpenSSH-Paketen zu gewährleisten (wie in anderen Antworten beschrieben). Die temporäre Datei verwendet /dev/shm(Shared Memory), falls verfügbar.

#!/bin/sh
usage () {
  printf '%s\n' "Usage: ssh-hostkey HOSTNAME [FPRINTHASH]"
}

ssh_hostkey () {
  local host="$1"
  local fprinthash="$2"
  local tmp=

  case "$host" in
    -h|--help|'')
      usage >&2
      return 1
      ;;
  esac

  case "$fprinthash" in
    md5|sha256|'') true;;
    *)
      usage >&2
      printf '%s\n' "Fingerprint hash may be 'md5' or 'sha256'" >&2
      return 2
      ;;
  esac

  if test -d /dev/shm
  then tmp="$(mktemp -d -p /dev/shm)"
  else tmp="$(mktemp -d)"
  fi

  trap 'trap - INT TERM EXIT; rm -rf "$tmp"' INT TERM EXIT
  ssh-keyscan "$host" > "$tmp/f" 2> /dev/null
  case "$fprinthash" in
    sha256|'') ssh-keygen -l -f "$tmp/f" 2> /dev/null;;
  esac
  case "$fprinthash" in
    md5|'') ssh-keygen -l -E md5 -f "$tmp/f" 2> /dev/null;;
  esac

  trap - INT TERM EXIT
  rm -rf "$tmp" > /dev/null 2>&1
}

ssh_hostkey "$@"
ejm
quelle