Проблема: у меня около 20-30 ssh-agent
идентичности. Большинство серверов отказываются от аутентификации с помощью Too many failed authentications
, так как SSH обычно не позволяет мне попробовать 20 разных ключей для входа.
На данный момент я указываю файл идентификации для каждого хоста вручную, используя IdentityFile
и IdentitiesOnly
директива, так что SSH будет пробовать только один ключевой файл, который работает.
К сожалению, это перестает работать, как только оригинальные ключи больше не доступны. ssh-add -l
показывает мне правильные пути для каждого ключевого файла, и они совпадают с путями в .ssh/config
, но это не работает. Очевидно, SSH выбирает отступ по подписи открытого ключа, а не по имени файла, что означает, что исходные файлы должны быть доступны, чтобы SSH мог извлечь открытый ключ.
С этим есть две проблемы:
Конечно, я мог бы извлечь открытые ключи из своих файлов идентификации и сохранить их на своем компьютере и на каждом удаленном компьютере, в который я обычно вхожу. Однако это не выглядит желательным решением.
Что мне нужно, так это возможность выбрать идентификатор из ssh-agent по имени файла, чтобы я мог легко выбрать правильный ключ, используя .ssh/config
или мимо -i /path/to/original/key
, даже на удаленном хосте, в который я подключился по SSH. Было бы даже лучше, если бы я мог «присваивать» ключи таким образом, чтобы мне даже не приходилось указывать полный путь.
Думаю, мне придется ответить на свой вопрос, поскольку, похоже, нет никакого способа запросить идентификацию по имени файла.
Я написал быстрые и грязные скрипты Python, которые создают файл открытого ключа в .ssh/fingerprints
для каждого ключа, который держит агент. Затем я могу указать этот файл, который не содержит секретного ключа, используя IdentityFile
и SSH выберет правильный идентификатор от агента SSH. Работает отлично и позволяет мне использовать агент для любого количества закрытых ключей, которое я хочу.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Dumps all public keys held by ssh-agent and stores them in ~/.ssh/fingerprints/, so that
they can be identified using the IdentityFile directive.
"""
import sys, os
import stat
import re
import envoy
RE_MATCH_FILENAME = re.compile(r'([^\\/:*?"<>|\r\n]+)\.\w{2,}$', re.IGNORECASE)
if os.getuid() == 0:
USERNAME = os.environ['SUDO_USER']
else:
USERNAME = os.environ['USER']
def error(message):
print "Error:", message
sys.exit(1)
def main():
keylist = envoy.run('ssh-add -L').std_out.strip('\n').split('\n')
if len(keylist) < 1:
error("SSH-Agent holds no indentities")
for key in keylist:
crypto, ckey, name = key.split(' ')
filename = os.path.join(os.environ['HOME'], '.ssh/fingerprints',
RE_MATCH_FILENAME.search(name).group(1)+'.pub')
with open(filename, 'w') as f:
print "Writing %s ..." % filename
f.write(key)
envoy.run('chmod 600 %s' % filename)
envoy.run('chown %s %s' % (USERNAME, filename))
if __name__ == '__main__':
main()
Бегать
ssh-add -L | gawk ' { print $2 > $3 ".pub" } '
на удаленном компьютере для автоматической генерации всех файлов открытых ключей (при условии, что открытые ключи в вашем .ssh/config
названы privateKeyFileName.pub
и никаких бессознательных путей). Вызов chown $USER .ssh/*
для тебя sudo
кейс.
Выбирая из принятого решения и предполагая, что вы просто хотите повторно использовать идентификатор, используемый для получения доступа к начальному серверу, тогда что-то вроде:
Host github.com
IdentitiesOnly yes
IdentityFile ~/.ssh/authorized_keys
достаточно.