在纯Bash中传递密码给SSH

56
我想使用bash脚本将密码传递给ssh(是的,我知道有可以使用的ssh密钥,但这不是我的意图)。
我发现一些解决方案使用了expect,但因为它不是标准的bash工具,所以我想知道是否可以使用管道来实现这一点。
有人能向我解释一下,为什么像这样的东西:
echo "password\n" | ssh somehost.com
或者
ssh somehost.com <(echo "password\n")

无法工作?有没有可能让它工作?也许可以将ssh作为不同的进程执行,获取其PID,然后直接向其发送一个字符串?


你需要获取sshpass。 - John C
6
好的,我会尽力进行翻译。以下是需要翻译的内容:相关链接:http://serverfault.com/questions/241588/how-to-automate-ssh-login-with-password如何自动化使用密码进行SSH登录? - Tom Fenech
1
虽然这个问题在stackoverflow上可能听起来与主题无关,但我没有在其他任何地方找到它被问过。这个问题和答案帮助我理解为什么管道对ssh不起作用。(“printf user/pass | vpn user@HOST”可以工作。) - Weishi Z
非常相关:如何将密码传递给scp? - Gabriel Staples
3个回答

88

虽然您无法从命令行指定密码,但是您可以使用ssh密钥或按照John C.的建议使用sshpass或使用expect脚本。

要使用sshpass,您需要先安装它。然后,

sshpass -f <(printf '%s\n' your_password) ssh user@hostname

与其使用 sshpass -p your_password,如评论中的 Charles Duffy 所提到的,更安全的做法是从文件或变量中提供密码,而不是从命令行中提供。

顺便解释一下 <(command) 语法。Shell 执行圆括号内的命令,并用文件描述符替换整个内容,该文件描述符连接到命令的标准输出。您可以从此答案中了解更多:https://unix.stackexchange.com/questions/156084/why-does-process-substitution-result-in-a-file-called-dev-fd-63-which-is-a-pipe


这并不是我问题的确切答案,但谢谢您。对于我来说,sshpass是一个非常好的解决方案。 - Liberat0r
通常情况下,您需要安装它。 - CS Pei
3
从安全角度考虑,密码绝不能通过命令行传递--命令行可被整个系统看到;即使在启动后更改其命令行的命令也容易被捕获。如果您必须使用该工具,有其他更安全的sshpass使用模式。 - Charles Duffy
1
你可以在答案中展示 sshpass -f <(printf '%s\n' your_password) ssh user@hostname,以便更好地展示高效的最佳实践方法。(因为 printf 是一个 shell 内置命令,它不会作为一个独立的命令执行,并通过 procfs 暴露其 argv)。 - Charles Duffy
1
$ brew search sshpass“我们不会添加sshpass,因为它会让新手SSH用户太容易破坏SSH的安全性。” 这是全面的。不要使用非交互式密码。请使用SSH密钥。 - Vojtěch Pithart
显示剩余7条评论

49

由于没有确切的答案回答我的问题,我进行了一些调查,想知道为什么我的代码不起作用,而其他解决方案却可以正常工作,并决定发布我找到的内容来完成这个主题。

事实证明:

"ssh使用直接TTY访问以确保密码确实是由交互式键盘用户发出的。" sshpass manpage

这就回答了问题,为什么在这种情况下管道不起作用。显然的解决方案是创建条件,使ssh“认为”它是在常规终端中运行,由于可以通过简单的posix函数实现,因此超出了简单的bash提供的范围。


12
既然你链接到了sshpass,我认为你应该给那个人的答案以功劳。 - Patrick
6
我建议您先阅读问题内容,而不是添加与主题无关的评论。 - Liberat0r
2
如果您的问题确实只是关于为什么某个事物-X不起作用,那么您的标题应该反映出这一点,而不是关于如何完成事物-X本来应该执行的目标。目前,问题的主体集中在那个领域,但标题却全部关于完成任务。 - Charles Duffy
2
@CharlesDuffy,“纯Bash”如何不反映需要使用标准Bash调用?你做了什么样的思维锻炼才得出这样的结论? - Błażej Michalik
2
@BłażejMichalik,我的观点是标题应该反映出问题在正文中的意图。我不反对OP的意图,即不依赖于POSIX未指定的工具,内置于bash或作为SSH软件包的一部分提供的工具。但我反对他们的问题标题与问题意图不符。 - Charles Duffy
显示剩余2条评论

0
如果您需要使用密码验证,则更安全的方法是从密码保险库将密码发送到剪贴板,然后在ssh提示时只需粘贴即可。在以下脚本中,凭据被传递到密码保险库pass,然后任何其他参数都被传递给ssh。
您可以在其他脚本中使用以下脚本来进一步自动化ssh使用。
例如:
#!/bin/bash
USAGE="USAGE: passtossh credential ..."
[[ $# -lt 2 ]] && echo "$USAGE" && exit 64
CRED="$1"
shift
echo "Creating a ssh connection using credentials $CRED with parameters $@ ."
echo "$(pass "$CRED")" | tr -d '\n' | pbcopy
ssh $@

你可以像这样使用这个脚本(例如ssh到一个主机并附加任何额外的参数):

$ passtossh my_credential user@host -L 8888:localhost:8888

当提示时,只需粘贴密码即可。Pbcopy是MacOS的实用程序,用于将stdin发送到剪贴板。对于Windows,请使用clip,对于Linux,请参见例如link

好处是密码不会出现在日志中,而且密码只能通过密码保险库的身份验证访问。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接