По крайней мере, для моей установки, использование ssh-keyscan
невозможно из-за моего обширного ~/.ssh/config
файла. Я использую множество прокси-команд, хостов перехода и альтернативных объявлений Hostname
.
Например:
# Connect to Tor nodes
Host *.onion
ProxyCommand socat - SOCKS4A:localhost:%h:%p,socksport=9050
# Work jump box
Host bastion
Hostname bastion.work.com
# Office system, e.g. bob.office -> bastion -> bob.work.com
Host *.office
ProxyCommand ssh bastion nc -w600s $(echo "%h" |sed 's/\.office$/work.com/') %p
# Home system, e.g. adam -> home.com -> adam-laptop.local
Host adam
Hostname adam-laptop.local
ProxyJump home.com
Ничто из перечисленного не будет работать.
Вот скрипт, который должен работать для остальных:
#!/usr/bin/awk -f
!/^#/ && NF > 2 {
split($1, hosts, ",")
key_type = $2
gsub(/^ssh-/, "", key_type)
gsub(/-.*/, "", key_type)
for (h in hosts) {
p = index(hosts[h], "]:") # [host]:port (supports raw IPv6 hosts)
if (!p && hosts[h] ~ /^[^:]+:[0-9]+$/) p = index(hosts[h], ":") # host:port
if (p > 0) {
port = substr(hosts[h], p + 2)
gsub("\[|\]?:" port, "", hosts[h])
} else {
port = 22
}
if (seen[key_type,port,hosts[h]]++) next # prevent duplicate lookups
if (port_list[key_type,port]) { comma = "," } else { comma = "" }
port_list[key_type,port] = port_list[key_type,port] comma hosts[h]
}
}
END {
for (tp in port_list) {
split(tp, a, SUBSEP)
system("echo ssh-keyscan -t " a[1] " -p " a[2] " " port_list[tp])
}
}
Снимите echo
детали для запуска, как только вы убедитесь, что это сделает то, что вы хотите.
Анализирует строки без комментариев и с полями 3+ (так как формат host_list key_type key_hash
). Он разделяет список хостов, так как он может быть разделен запятыми, и требуется дальнейший анализ, потому что он может содержать порты, но ssh-keyscan
не может принимать хосты в формате, используемом known_hosts
.
Существует два способа указания порта:
- Старый стиль, который не работает с голыми адресами IPv6, это
host:port
- Новый стиль, который требуется для пустых адресов IPv6, -
[host]:port
p
устанавливается в положение ]:
, если присутствует (новый стиль). Если эта строка отсутствует, мы проверяем старый стиль и сбрасываем p
.
Если p
положительно, у нас есть спецификация порта. Извлеките порт и удалите (это и квадратные скобки) из имени хоста. В противном случае порт равен 22.
На всякий случай, если есть повторяющиеся записи, мы проверяем их и продолжаем, если уже видели комбинацию типа, порта, хоста (x++
имеет значение false (0) только при первом запуске). Наконец, мы помещаем хост в разделенную запятыми строку списка в массиве port_list
, как указано кортежем типа и порта.
После прочтения всего файла known_hosts, мы перебираем пары кортежей type,port
, которые задают массив port_list
, разделяем их на массив с именем a
и запускаем на них ssh-keyscan
.
Запустите это как awk -f 'this_script.awk' ~/.ssh/known_hosts
и, если вам нравятся ssh-keyscan
команды, которые он выплевывает, удалите echo
из системной команды и повторите запуск.
Не передавайте эти выходные данные в ~/.ssh/known_hosts
! Вы можете вручную просмотреть результаты (и, возможно, отфильтровать комментарии). Кроме того, вы не можете перенаправить вывод на один из файлов, используемых во вводе.