Ssh

通過文件名從 ssh-agent 中選擇身份

  • January 5, 2022

問題:我有大約 20-30 個ssh-agent身份。大多數伺服器拒絕使用 進行身份驗證Too many failed authentications,因為 SSH 通常不會讓我嘗試 20 個不同的密鑰來登錄。

目前,我正在手動為每個主機指定身份文件,使用IdentityFileIdentitiesOnly指令,這樣 SSH 將只嘗試一個有效的密鑰文件。

不幸的是,一旦原始密鑰不再可用,這將停止工作。ssh-add -l向我顯示每個密鑰文件的正確路徑,它們與 中的路徑匹配.ssh/config,但它不起作用。顯然,SSH 通過公鑰簽名而不是文件名來選擇身份,這意味著原始文件必須可用,以便 SSH 可以提取公鑰。

這有兩個問題:

  • 一旦我拔下持有鑰匙的快閃記憶體驅動器,它就會停止工作
  • 它使代理轉發無用,因為遠端主機上沒有密鑰文件

當然,我可以從我的身份文件中提取公鑰並將它們儲存在我的電腦上,以及我通常登錄的每台遠端電腦上。不過,這看起來不是一個理想的解決方案。

我需要的是通過文件名從 ssh-agent 中選擇一個身份的可能性,這樣我就可以使用.ssh/config或 通過傳遞輕鬆選擇正確的密鑰-i /path/to/original/key,即使在我通過 SSH 連接到的遠端主機上也是如此。如果我可以“暱稱”這些鍵,那就更好了,這樣我什至不必指定完整路徑。

我想我必須回答我自己的問題,因為似乎沒有任何方法可以通過文件名請求身份。

.ssh/fingerprints我編寫了一個快速而簡單的 Python 腳本,它為代理持有的每個密鑰創建一個公鑰文件。然後我可以指定這個不包含密鑰的文件,使用IdentityFileSSH 將從 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()

引用自:https://serverfault.com/questions/401737