如何仅在需要时才要求输入 SSH 密钥密码?

如何仅在需要时才要求输入 SSH 密钥密码?

(我已经阅读了该网站上许多看起来相关的问题,我相信这是一个真正的新问题。)

我在许多服务器上都有许多密钥,并且它们都受到密码保护。

我喜欢输入密码,就像我喜欢输入密码一样——这确实是一种生产力消耗。

  • ssh代理+ssh 添加命令可以在登录 shell 上使用,这意味着您只需在登录时输入一次密码

  • 钥匙链可用于在注销后保持 ssh 代理的活动状态,因此,例如,您可以拥有它,这样您只需在启动时输入密码短语一次,或者您可以让它使其保持活动状态一个小时左右。

我遇到的问题是,这两种解决方案通常都是在 shell 登录(例如.zshrc)中启动的,依赖于我在登录时输入密码,即使我不需要解锁它。 (我对钥匙串让特工无限期地存活感到不满意。)

我想要的是提示输入密码(对于代理)仅在需要时

所以我可以登录到服务器 A,做一些事情,然后 ssh 到服务器 B 并在那时候被要求提供密码。在服务器B上做一些事情,注销。回到 A,做更多的事情,再次 ssh 到 B,不需要我的密码(它由代理持有)。

我注意到这在 Gnome 等图形桌面上是可能的 - 当您尝试 ssh 时,您会收到一个弹出窗口,要求输入密码来解锁您的私钥。这就是我所追求的,但来自控制台。

答案1

不要在任何 shell 启动脚本中添加任何内容,这是不必要的黑客行为。

相反,添加

AddKeysToAgent yes

到你的 .ssh/config

像这样,当您第一次 ssh 到另一个盒子时,ssh-add 会自动运行。仅当 ssh-agent 的密钥过期或重新启动后,您才需要重新输入密钥。

答案2

兹什有一个preexec钩子,可以在执行命令行上输入的命令之前执行一个函数。这是一个在命令行中查找的钩子ssh,如果找到,则检查 ssh 代理是否存在。如果没有找到,它将运行钥匙串。

因此,这样,钥匙串仅在 ssh 命令之前运行,并且仅在需要时运行。

把这个放在你的~/.zshrc

function check_ssh {
  [[ $3 =~ '\bssh\b' ]] || return
  [[ -n "$SSH_AGENT_PID" && -e "/proc/$SSH_AGENT_PID" ]] \
    && ssh-add -l >/dev/null && return
  eval `keychain --eval id_dsa --timeout 60`
}    
autoload -U add-zsh-hook
add-zsh-hook preexec check_ssh

这里发生的事情是每当键入命令时,check_ssh在执行命令之前调用。

该函数的第一行检查扩展命令是否ssh使用 Zsh 正则表达式。两边都ssh必须有字边界。\b如果没有找到,则函数返回。

下一行检查环境变量中是否存在 SSH 代理进程,并且该进程仍然存在于进程表中,然后至少有一个密钥已添加到代理中。如果一切正常,则 ssh 代理已设置完毕,我们不需要执行任何操作,因此它会返回。

最后我们启动钥匙串,让代理保持活动一个小时。

它仍然留下有关嵌入式 ssh 内容的问题,例如gitorrsyncscpas 不会触发该函数(您可以将它们添加到正则表达式中)。

答案3

对于 zsh,我编写了一组实用程序和包装器来或多或少地完成您想要的操作:https://www.vinc17.net/unix/index.en.html#zsh-ssh-utils

实际上这甚至更多,因为它将ssh-agent被所有登录会话共享(桌面或通过 SSH,如果您从中启动登录 shell,也支持 GNU Screen,例如在文件shell -zsh~/.screenrc),并且只有在最后一个会话终止。

注意:我的所有密钥仅使用一个密码。我不确定不同密码的行为;可能需要一些改变。

相关内容