如何仅在需要时才询问SSH密钥密码?


15

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

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

我喜欢输入密码和输入密码一样多-这确实浪费了生产力。

  • ssh-agent + ssh-add命令可用于登录外壳,这意味着您只需在登录时输入一次密码

  • 钥匙串可用于使ssh-agent在注销后保持活动状态,例如,您可以拥有它,因此只需在启动时输入一次密码即可,或者可以使其保持活动状态约一个小时。

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

只想在需要时才提示您输入密码(对于座席)。

这样我就可以登录到服务器A,做一些东西,然后ssh到服务器B,并在该点被要求提供密码。在服务器B上做一些事情,注销。回到A上,做一些更多的事情,再次向B SSH,不需要我的密码短语(由代理持有)。

我注意到这在Gnome之类的图形桌面上是可能的-您会弹出一个窗口,要求您在尝试ssh时立即解锁密码。所以这就是我想要的,但是要从控制台开始。


为什么不生成没有密码短语的ssh-key?如果您还是要经历所有这些麻烦?
devnull

1
如果有人闯入并且有无密码密钥(或活动的ssh代理),他们也可以访问许多其他服务器。同样,无密码密钥也可以被窃取并在其他地方使用。
artfulrobot

据我所知,在不牺牲某种程度的安全性的情况下,您无法做任何想做的事情,这听起来像您不想做。托马斯·尼曼(Thomas Nyman)在这里有一个深入的答案,如果您还没有读过的话,有很多可能性:unix.stackexchange.com/a/90869/82289。我在公司使用一个中间服务器来解决这个问题,该中间服务器管理与Tmux的ssh会话。
devnull

@DevNull似乎很奇怪,您可以在台式机上执行此操作,但不能在终端上执行操作,不是吗?如果没有添加任何键,是否肯定只需要代理跳到tty?这一定是gui的工作方式吗?
artfulrobot

您可以在这里查看我的答案:unix.stackexchange.com/a/184160/89706(问题链接:unix.stackexchange.com/questions/90853/…
Johnny Wong

Answers:


16

不要在您的任何Shell启动脚本中添加任何内容,这是不必要的黑客手段。

相反,添加

AddKeysToAgent yes

到您的.ssh / config

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


我希望人们在投票时发表评论。如果不正确很重要,我们知道为什么不正确。感谢您的发帖,我没有时间亲自尝试您的建议。
artfulrobot '16

我也想知道,也许是因为我的交叉职位?
Toby

这对我有用。但是,这是对openssh(7.2)的最新添加。万一它对任何人都有帮助,在Debian Sid中可以使用openssh 7.3。
artfulrobot

@artfulrobot:奇怪,因为我有同样的行为(在ssh第一次调用时自动添加ssh)已经工作了好多年,直到它在一段时间前终于停止。搜索原因,我找到了AddKeysToAgent并认为它停止的原因是偶然地我必须清除.ssh / config和AddKeysToAgent。现在我想知道为什么它在OpenSSH 7.2发布之前就可以正常工作了?我没有想象到这:-)
Toby

@Toby这正是我需要的。不幸的是,ssh-agent似乎并没有在kubuntu中自动启动,所以这是我需要解决的下一件事。
Ogaday'3

7

Zsh具有在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东西的问题,例如gitrsyncscp不会触发功能(您可以将它们添加到正则表达式中)。


即使没有zsh,也可以创建一个具有相同效果的简短脚本,并将其放置PATH在实际ssh客户端之前。如果他们阅读而不是直接运行rsync,甚至可能与et al 一起工作。PATH/usr/bin/ssh
ilkkachu

2

对于zsh,我已经编写了一组实用程序和包装程序来做您想要做的事:https : //www.vinc17.net/unix/index.en.html#zsh-ssh-utils

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

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


哇,这是很多代码。做得好,感谢您的分享。我认为我需要更简单的东西-SSH对我来说是一个非常漂亮的核心工具。
artfulrobot
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.