我想在脚本中使用SSH
,但该脚本不会在我的计算机上执行。
我的实现有两个限制。
- 我不能超出shell的标准,因此我不能使用
expect
,因为我不知道它是否可用于此计算机。 - 我不能指望这台计算机拥有
SSH
的公钥
。
有哪些可能的选项和解决方案?
如何以自动化和安全的方式提供所需密码给ssh而不添加额外的依赖项?
是否可以在脚本内部提供密码?
提前感谢大家:)
我想在脚本中使用SSH
,但该脚本不会在我的计算机上执行。
我的实现有两个限制。
expect
,因为我不知道它是否可用于此计算机。SSH
的公钥
。有哪些可能的选项和解决方案?
如何以自动化和安全的方式提供所需密码给ssh而不添加额外的依赖项?
是否可以在脚本内部提供密码?
提前感谢大家:)
安装sshpass,然后运行以下命令:
sshpass -p "yourpassword" ssh -o StrictHostKeyChecking=no yourusername@hostname
出于安全考虑,您必须避免在命令行中提供密码,否则运行ps命令的任何人都可以看到您的密码。最好使用sshpass实用工具,例如:
#!/bin/bash
export SSHPASS="your-password"
sshpass -e ssh -oBatchMode=no sshUser@remoteHost
您可能对如何从Bash脚本中使用密码运行sftp命令?感兴趣。
ssh-agent
shell中执行。#!/usr/bin/env ssh-agent /usr/bin/env bash
KEYFILE=`mktemp`
cat << EOF > ${KEYFILE}
-----BEGIN RSA PRIVATE KEY-----
[.......]
EOF
ssh-add ${KEYFILE}
# do your ssh things here...
# Remove the key file.
rm -f ${KEYFILE}
ssh-keygen -f ~/.ssh/my-script-key
来创建专门用于此目的的私钥,但这样您还需要添加公钥到服务器的例程。我完全同意所有认为这几乎肯定是一个非常糟糕的主意的人。然而,如果你已经评估了你的需求并想知道如何做到这一点,在不使用密钥和安装任何其他程序的情况下,只需使用Bourne Shell机制是完全可能的。
在评估了安全风险之后,请自行承担风险
创建一个名为/path/to/saypass
的程序,输出密码,例如以下最简脚本:
#!/bin/sh
echo 'secret'
chmod +x /path/to/saypass
SSH_ASKPASS="/path/to/saypass" DISPLAY=anything setsid ssh username@hostname [farcommand]
ssh
,它使用你的saypass
程序来获取密码。(将/path/to
替换为你脚本的路径;anything
可以是字面上的这个字符串;将username@hostname
替换为你的详细信息。)SSH_ASKPASS
和DISPLAY
- 然后运行setsid
- setsid
再运行没有控制终端的ssh
- ssh
连接到远程hostname
- 在本地运行saypass
获取密码
- 将密码发送给远程服务器
- 假设密码正确
- 运行farcommand
(如果提供了)或者一个交互式shelldate
或hostname
来测试可选的farcommand
。ssh
有一些环境变量可以用来选择一个程序来提供密码。这个设计是为了与X11用户界面一起使用的,但也可以用于我们的目的。
ssh(1)
手册页上说:
所以:你需要一个输出密码的程序(shell脚本或其他任何类型)。然后你需要说服SSH_ASKPASS
如果ssh
需要密码短语,它将从当前终端读取密码短语,如果它是从终端运行的。如果ssh
没有与之关联的终端,但设置了DISPLAY
和SSH_ASKPASS
,它将执行由SSH_ASKPASS
指定的程序,并打开一个X11窗口来读取密码短语。
ssh
使用它:
SSH_ASKPASS
设置为/path/to/saypass
DISPLAY
设置为一些愚蠢的东西setsid
的作用)你可以将它们组合在以下的sh
命令中:
SSH_ASKPASS="/path/to/saypass" DISPLAY=anything setsid ssh username@hostname [command]
ssh
将执行以下两个命令之一:
/path/to/saypass "Password:"
/path/to/saypass "username@hostname's password:"
The authenticity of host '*hostname* (*ipaddress*)' can't be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no)?
ssh
会像这样运行您的命令:/path/to/saypass "Please type 'yes' or 'no':"
以下是一个用于创建、使用和删除主脚本中的saypass
的单一脚本。大家都会告诉你不要将明文密码放在文件中,也永远不要硬编码密码。他们这样告诉你是有充分理由的:它会给你带来很多麻烦。请自行承担风险。
#!/bin/sh
echo "#!/bin/sh\necho 'secret';rm -f /tmp/saypass.$$" > /tmp/saypass.$$
chmod 775 /tmp/saypass.$$
SSH_ASKPASS="/tmp/saypass.$$" DISPLAY=anything setsid ssh "$@"
这也适用于scp
,在ssh
之上的复制程序:
SSH_ASKPASS=/path/to/saypas DISPLAY=anything setsid scp username@hostname:/path/to/farfile .
除非在非常紧急的情况下,千万不要使用这个方法,比如当你有数百台电脑且无法安装任何像是ssh密钥、sshpass甚至expect之类的东西。
如果必须使用这种技术,请将密码放在一个文件中,并让saypass
从那里获取。 尽可能保护好saypass
的安全性;你可以通过环境变量将信息传递给它。
我不知道man页面上所说的"打开X11窗口"是什么意思,在我的测试中没有发生这样的事情。
测试环境:
ssh
,否则没有其他可能性。但是大多数编程语言都有库绑定,比如C、Python、PHP等等。您可以使用这些语言编写程序,以便自动传递密码。但是请注意,这当然是一个安全问题,因为密码将以明文形式存储在该程序中。ssh
命令期望从终端输入密码。这就是为什么需要使用expect来模拟终端。也许有一种简单的方法可以做到同样的事情,但我不知道怎么做。不过你可以通过谷歌搜索找到100行代码实现相同的功能。 - hek2mgl