Получить отпечаток ключа SSH сервера

84

Есть ли способ программно получить отпечаток ключа сервера SSH без аутентификации ?

Я пытаюсь ssh -v user@host false 2>&1 | grep "Server host key", но это зависает в ожидании пароля, если аутентификация на основе ключа не настроена.

goncalopp
источник

Ответы:

72

Вы можете сделать это, комбинируя ssh-keyscanи 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

(к сожалению, намного проще ssh-keyscan host | ssh-keygen -l -f /dev/stdinне работает)

Андреас Визе
источник
1
Может ssh-keygen -l -f - <(ssh-keyscan host), правда?
CVn
21
OpenSSH> = 7.2 ssh-keyscan умеет читать со стандартного ssh-keyscan host | ssh-keygen -lf -
ввода
1
Просто сделайте:ssh-keygen -l -f <(ssh-keyscan host)
Кристофер
1
Это довольно плохое выражение для сценариев оболочки, поскольку оно зависит от оболочки, поддерживающей его, а оболочка POSIX - нет.
Андреас Визе
2
ssh-keygen -l -f -действительно работает так, как ожидалось в ssh-keygen 7.2 и выше. Он производит несколько строк комментариев к STDERR, которые могут быть отфильтрованы, как упоминалось в ответе Энтони Геогегана илиssh-keyscan host 2>/dev/null | ssh-keygen -l -f -
Седрик Найт
57

Мне недавно пришлось сделать это самому, поэтому я решил добавить ответ, который показывает, как это можно сделать (с версиями OpenSSH 7.2 или новее ) в одну строку, используя подстановку процессов:

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

Следующий текст объясняет, как работают эти команды, и выделяет некоторые различия в поведении между старыми и новыми версиями утилит OpenSSH.

Получить открытые ключи хоста

Команда ssh-keyscanбыла разработана таким образом, чтобы пользователи могли получать открытые ключи хоста без аутентификации на сервере SSH. Из его справочной страницы:

ssh-keyscanутилита для сбора открытых ключей хоста ssh нескольких хостов Это было разработано, чтобы помочь в создании и проверке ssh_known_hostsфайлов.

Тип ключа

Тип ключа, который нужно получить, указывается с помощью -tпараметра.

  • rsa1 (устаревшая версия протокола SSH 1)
  • rsa
  • dsa
  • ecdsa (последние версии OpenSSH)
  • ed25519 (последние версии OpenSSH)

В современных выпусках OpenSSH типами ключей по умолчанию для выборки являются rsa (начиная с версии 5.1), ecdsa(начиная с версии 6.0) и ed25519(начиная с версии 6.7).

С более старыми версиями из ssh-keyscan(до OpenSSH версии 5.1), то по умолчанию тип ключ был устаревают rsa1(SSH протокол 1) , так что основные типы должны быть явно указаны:

ssh-keyscan -t rsa,dsa hostname

Получите хэши отпечатков пальцев ключей Base64

ssh-keyscanпечатает ключ хоста SSH-сервера в формате Base64 . Чтобы преобразовать это в хэш отпечатка пальца, ssh-keygenможно использовать утилиту с -lвозможностью печати отпечатка пальца указанного открытого ключа.

При использовании Bash, Zsh (или оболочки Korn), подстановка процесса может быть использована для удобной однострочной:

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

Примечание . В версиях OpenSSH до 7.2 функции, используемые ssh-keygenдля чтения файлов, не очень хорошо обрабатывали именованные каналы (FIFO), поэтому этот метод не будет работать, что потребует использования временных файлов.

Алгоритмы хеширования

Последние версии ssh-keygenпечати SHA256 отпечатков пальцев хэши ключей. Чтобы получить MD5- хэши отпечатков ключей сервера (старое поведение), -E можно использовать параметр, чтобы указать алгоритм хеширования:

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

Использование конвейера

Если используется оболочка POSIX (например, dash), в которой не предусмотрена подстановка процессов, другие решения, использующие временные файлы, будут работать. Однако в более новых версиях OpenSSH (начиная с 7.2) можно использовать простой конвейер, поскольку он ssh-keygenбудет принимать -имя файла для стандартного входного потока, что позволяет использовать однострочную команду конвейера.

ssh-keyscan hostname 2>/dev/null | ssh-keygen -E md5 -lf -
Энтони Дж - справедливость для Моники
источник
Хороший и тщательный ответ, это, безусловно, лучше, чем иметь временный файл! Могу ли я предложить вам вначале TL; DR с версией процесса замещения, чтобы нетерпеливые люди могли быстрее ее найти? :)
goncalopp
3
Кажется, не работает на Ubuntu 14.04 LTS; Я получаю сообщение об ошибке "/ dev / fd / 63 не является файлом открытого ключа". Подпроцесс работает.
Мелле
@melleb Я нашел то же самое в системе 12.04, к которой у меня есть доступ. Я подозреваю, что ssh-keygenиз более старых версий OpenSSH возникают проблемы с чтением из FIFO / именованного канала. Я посмотрю на это (и обновлю свой ответ), когда у меня будет немного свободного времени.
Энтони Дж. - справедливость для Моники
3
@melleb Потратив много времени на загрузку различных выпусков исходного кода и вставив printfв do_fingerprint()функцию операторы отладки , я обнаружил, что в версиях OpenSSH до 7.2 функции, используемые ssh-keygenдля чтения файлов, не очень хорошо обрабатывали именованные каналы (FIFO), поэтому метод замены процесса не будет работать.
Энтони Дж. - правосудие для Моники
Это работает, но если вы используете его для проверки отпечатка пальца, пользователи должны знать, что есть условие гонки: отпечаток, который вы проверяете с помощью этой команды, не обязательно совпадает с ключом, который вы получаете, если вы не сбросили ключ перед вызовом ssh- кейген на это.
CodeGnome
20

nmapпредоставляет эту возможность с помощью ssh-hostkeyсценария.

Чтобы вернуть шестнадцатеричный отпечаток ключа:

$ nmap [SERVER] --script ssh-hostkey

Чтобы вернуть содержимое ключа:

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

Чтобы вернуть визуальный пузырь ключа

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

Чтобы вернуть все вышеперечисленное:

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

Источник: nmap документы

ручей
источник
3
Предполагают ли эти примеры, что SSH всегда работает на порту 22? Что делать, если ssh прослушивает нестандартный порт?
Мартин Вегтер
3
@MartinVegter (перефразируя Guarin42, который не может комментировать :) У nmap есть -pопция, которая может указывать порт, например -p 22000. Также возможно использовать -vvопцию для увеличения многословия (объем предоставленной информации)
goncalopp
2

filezilla отображает ключи, хэшированные с помощью md5, в шестнадцатеричном формате.

чтобы найти это на вашем компьютере с Ubuntu Linux, используйте эту команду:

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

примечание: замените "localhost" на ip машины, которую вы хотите проверить.

Cameron
источник
1

Вот сценарий оболочки (в основном оболочка Bourne, но с использованием localключевого слова, которое доступно в большинстве современных /bin/sh), я написал для этого. Используйте это как ssh-hostkey hostname. Он покажет отпечатки пальцев в формате sha256 и md5 для всех ключей хоста для данного имени хоста или IP-адреса. Вы также можете вручную указать « md5» или « sha256» в качестве второго аргумента, чтобы показать только этот конкретный формат.

Он использует временный файл вместо конвейера, чтобы сделать его совместимым со старыми пакетами OpenSSH (как описано в других ответах). Временный файл использует /dev/shm(разделяемую память), если доступно.

#!/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
источник