Obtenir l'empreinte de la clé du serveur SSH

83

Existe-t-il un moyen d' obtenir par programme une empreinte de clé de serveur SSH sans s'authentifier auprès de celle-ci?

J'essaie ssh -v user@host false 2>&1 | grep "Server host key", mais l'attente d'un mot de passe est suspendue si l'authentification par clé n'est pas configurée.

goncalopp
la source

Réponses:

71

Vous pouvez le faire en combinant ssh-keyscanet 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

(malheureusement, le plus simple ssh-keyscan host | ssh-keygen -l -f /dev/stdinne fonctionne pas)

Andreas Wiese
la source
1
Peut ssh-keygen -l -f - <(ssh-keyscan host)- être que, cependant?
un CVn
21
OpenSSH> = 7.2 ssh-keyscan est capable de lire à partir de stdin:ssh-keyscan host | ssh-keygen -lf -
mykhal
1
Il suffit de faire:ssh-keygen -l -f <(ssh-keyscan host)
Christopher
1
C'est une expression plutôt mauvaise pour les scripts shell, car elle dépend d'un shell qui le supporte, ce que ne fait pas le shell POSIX.
Andreas Wiese
2
ssh-keygen -l -f -fonctionne vraiment comme prévu dans ssh-keygen 7.2 et supérieur. Il produit des lignes de commentaires à STDERR qui peuvent être filtrées, comme mentionné dans la réponse de Anthony Geoghegan oussh-keyscan host 2>/dev/null | ssh-keygen -l -f -
Cedric Knight
56

J'ai récemment eu à le faire moi-même, alors j'ai pensé ajouter une réponse qui montre comment cela peut être fait (avec les versions d' OpenSSH 7.2 ou plus récentes ) sur une ligne en utilisant la substitution de processus:

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

Le texte suivant explique le fonctionnement de ces commandes et met en évidence certaines des différences de comportement entre les versions les plus anciennes et les plus récentes des utilitaires OpenSSH.

Récupérer les clés de l'hôte public

La ssh-keyscancommande a été développée pour que les utilisateurs puissent obtenir des clés d’hôte publiques sans s’authentifier auprès du serveur SSH. De sa page de manuel:

ssh-keyscanest un utilitaire permettant de rassembler les clés d’hôte ssh publiques d’un certain nombre d’hôtes. Il a été conçu pour faciliter la construction et la vérification des ssh_known_hostsfichiers.

Type de clé

Le type de clé à récupérer est spécifié à l'aide de l' -toption.

  • rsa1 (version 1 du protocole SSH obsolète)
  • rsa
  • dsa
  • ecdsa (versions récentes d'OpenSSH)
  • ed25519 (versions récentes d'OpenSSH)

Dans les versions récentes d'OpenSSH, les types de clé à récupérer par défaut sont rsa (depuis la version 5.1), ecdsa(depuis la version 6.0) et ed25519(depuis la version 6.7).

Avec les anciennes versions de ssh-keyscan(avant OpenSSH version 5.1), le type de clé par défaut étant obsolète rsa1(protocole SSH 1), il fallait donc spécifier explicitement les types de clé:

ssh-keyscan -t rsa,dsa hostname

Récupère les empreintes digitales des clés Base64

ssh-keyscanimprime la clé d’hôte du serveur SSH au format codé Base64 . Pour convertir ceci en un hachage d'empreinte digitale, l' ssh-keygenutilitaire peut être utilisé avec son -loption pour imprimer l'empreinte digitale de la clé publique spécifiée.

Si vous utilisez Bash, Zsh (ou le shell Korn), la substitution de processus peut être utilisée pour un one-liner très pratique:

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

Remarque : Avec les versions d'OpenSSH antérieures à 7.2, les fonctions utilisées par ssh-keygenpour lire les fichiers ne géraient pas très bien les canaux nommés (FIFO), de sorte que cette méthode ne fonctionnait pas et nécessitait donc l'utilisation de fichiers temporaires.

Algorithmes de hachage

Les versions récentes des ssh-keygenempreintes d' empreinte digitales SHA256 des clés. Pour obtenir les hachages MD5 des empreintes de clé de serveur (l'ancien comportement), l' -E option peut être utilisée pour spécifier l'algorithme de hachage:

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

Utiliser un pipeline

Si vous utilisez un shell POSIX (tel que dash) qui ne comporte pas de substitution de processus, les autres solutions utilisant des fichiers temporaires fonctionneront. Cependant, avec les versions plus récentes d'OpenSSH (depuis la version 7.2), un simple pipeline peut être utilisé car ssh-keygenacceptera -comme nom de fichier pour le flux d'entrée standard, permettant ainsi une commande de pipeline d'une ligne.

ssh-keyscan hostname 2>/dev/null | ssh-keygen -E md5 -lf -
Anthony G - justice pour Monica
la source
Belle et complète réponse, c'est certainement mieux que d'avoir un fichier temporaire! Puis-je vous suggérer de fournir au début un TL; DR avec la version de substitution de processus, pour que les personnes impatientes le trouvent plus rapidement? :)
Goncalopp
3
Ne semble pas fonctionner sur Ubuntu 14.04 LTS; J'obtiens une erreur "/ dev / fd / 63 n'est pas un fichier de clé publique". Le sous-processus fonctionne.
Melle
@melleb J'ai trouvé la même chose sur un système 12.04 auquel j'ai accès. Je soupçonne que ssh-keygendes versions plus anciennes d'OpenSSH ont un problème de lecture à partir du tube FIFO / named. J'examinerai cela (et actualiserai ma réponse) lorsque j'aurai du temps libre.
Anthony G - justice pour Monica
3
@melleb Après avoir passé mon temps à télécharger diverses versions du code source et à insérer des printfinstructions de débogage dans la do_fingerprint()fonction, j'ai constaté qu'avec les versions d'OpenSSH antérieures à 7.2, les fonctions utilisées par les ssh-keygenfichiers pour lire les fichiers ne géraient pas très bien la méthode de substitution de processus ne fonctionnerait pas.
Anthony G - justice pour Monica
Cela fonctionne, mais si vous l'utilisez pour vérifier une empreinte digitale, les utilisateurs doivent être conscients qu'il existe une condition de concurrence critique: l'empreinte digitale que vous vérifiez avec cette commande n'est pas nécessairement celle de la clé que vous extrayez, à moins que vous ne la sauvegardiez avant d'appeler ssh- keygen dessus.
CodeGnome
20

nmapfournit cette capacité en utilisant le ssh-hostkeyscript.

Pour renvoyer l'empreinte hexadécimale de la clé:

$ nmap [SERVER] --script ssh-hostkey

Pour retourner le contenu de la clé:

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

Pour retourner la bulle visuelle de la clé

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

Pour renvoyer tout ce qui précède:

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

Source: docs nmap

Ruisseau
la source
3
Ces exemples supposent-ils que SSH fonctionne toujours sur le port 22? Que se passe-t-il si SSH écoute sur un port non standard?
Martin Vegter
3
@MartinVegter (en paraphrasant Guarin42, qui n'a pas pu commenter :) nmap a l' -poption qui peut spécifier un port, par exemple -p 22000. Il est également possible d'utiliser l' -vvoption pour augmenter la verbosité (quantité d'informations fournies)
goncalopp
2

filezilla affiche les clés hachées avec md5 au format hexadécimal .

pour le trouver sur votre machine linux ubuntu , utilisez cette commande:

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

remarque: remplacez "localhost" par l'adresse IP de la machine que vous souhaitez vérifier.

Cameron
la source
1

Voici un script shell (principalement shell Bourne mais utilisant le localmot-clé, qui est disponible dans la plupart des logiciels modernes /bin/sh), je l’ai écrit pour le faire. Utilisez-le comme ssh-hostkey hostname. Il affichera les empreintes digitales des formats sha256 et md5 pour toutes les clés hôte pour le nom d'hôte ou l'adresse IP donné. Vous pouvez également spécifier manuellement " md5" ou " sha256" en tant que deuxième argument pour afficher uniquement ce format particulier.

Il utilise un fichier temporaire à la place de la tuyauterie pour le rendre compatible avec les anciens packages OpenSSH (comme décrit dans d'autres réponses). Le fichier temporaire utilise /dev/shm(mémoire partagée) s'il est disponible.

#!/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
la source