Ssh
通過文件名從 ssh-agent 中選擇身份
問題:我有大約 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 連接到的遠端主機上也是如此。如果我可以“暱稱”這些鍵,那就更好了,這樣我什至不必指定完整路徑。
我想我必須回答我自己的問題,因為似乎沒有任何方法可以通過文件名請求身份。
.ssh/fingerprints
我編寫了一個快速而簡單的 Python 腳本,它為代理持有的每個密鑰創建一個公鑰文件。然後我可以指定這個不包含密鑰的文件,使用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()