bash 使用变量的值作为 scp、ssh 等的密码,而不是每次都提示用户输入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4594698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using a variable's value as password for scp, ssh etc. instead of prompting for user input every time
提问by Sandeepan Nath
AFAIK, the commands ssh
or scp
do not have/take a password parameter. Otherwise I could keep the password in a shell variable and probably get rid of the enter password prompt. If I write an scp command in my shell script, it prompts the user to input the password. I have multiple ssh and scp commands in my script and I do not want the user to enter the password every time. I would prefer to save the password in a shell variable in the beginning (by asking password once), then use it for every ssh or scp.
AFAIK,命令ssh
或scp
没有/采用密码参数。否则,我可以将密码保存在 shell 变量中,并可能摆脱输入密码提示。如果我在 shell 脚本中编写 scp 命令,它会提示用户输入密码。我的脚本中有多个 ssh 和 scp 命令,我不希望用户每次都输入密码。我更愿意在开始时将密码保存在 shell 变量中(通过询问密码一次),然后将它用于每个 ssh 或 scp。
I read about "public key identification" in this question. Is it related to the solution I am looking for?
我在这个问题中读到了“公钥识别” 。它与我正在寻找的解决方案有关吗?
Update
I read in How to use ssh command in shell script?why it is unsafe to specify passwords on the commandline. Does using expect
also store the password and is world visible (using ps aux
)? Is that the security issue with using expect
?
更新
我在如何在 shell 脚本中使用 ssh 命令?为什么在命令行上指定密码是不安全的。using 是否expect
也存储密码并且是世界可见的(使用ps aux
)?这是使用的安全问题expect
吗?
Further Explanation
To further make it clear, I am writing this shell script to automate code and database backup, do code upload, run necessary database queries, do all the things that are needed for a new version release of a LAMP projectfrom a developer system to a remote live server. My shell script will be there inside the main codebase of the project in every developer instance.
进一步说明
为了进一步说明,我正在编写这个 shell 脚本来自动执行代码和数据库备份、执行代码上传、运行必要的数据库查询、执行从开发人员系统发布新版本LAMP 项目所需的所有操作到远程实时服务器。我的 shell 脚本将位于每个开发人员实例中项目的主代码库中。
Requirement
要求
I want all developers (all may be working from different remote systems) knowing the SSH/FTP password to be able to use the shell by entering the ssh/ftp password same only at run-time once. I would prefer the password to be the ssh/ftp password
Note -I do not want other developers who don't know the SSH password to be able to use it (So I guess public key authentication will not work because it stores the passwords in the systems).
- I do not want any command line solution which stores the password in some log in the system and can be world visible using ps aux or something.
我希望所有开发人员(都可能在不同的远程系统上工作)知道 SSH/FTP 密码,以便能够通过仅在运行时输入相同的 ssh/ftp 密码来使用 shell。我希望密码是 ssh/ftp 密码
注意 -我不希望其他不知道 SSH 密码的开发人员能够使用它(所以我猜公钥身份验证不起作用,因为它将密码存储在系统中)。
- 我不想要任何将密码存储在系统中的某些日志中的命令行解决方案,并且可以使用 ps aux 或其他东西在世界范围内可见。
Opening Bounty
From all the answers so far and my anaylsis of those solutions, it looks like other than public key authentication all others are insecure. I am not yet sure if using expect
is insecure. I think it is otherwise the correct solution for me. In that case, I am getting command not found errors while trying to do that as already commented on one of the answers.
Opening Bounty
从目前所有的答案和我对这些解决方案的分析来看,看起来除了公钥认证之外,所有其他的都是不安全的。我还不确定使用expect
是否不安全。我认为这对我来说是正确的解决方案。在这种情况下,我在尝试执行此操作时收到命令未找到错误,正如已经对其中一个答案进行了评论。
From http://www.debianadmin.com/sshpass-non-interactive-ssh-password-authentication.html-
来自http://www.debianadmin.com/sshpass-non-interactive-ssh-password-authentication.html-
First and foremost, users of sshpass should realize that ssh's insistance on only getting the password interactively is not without reason. It is close to be impossible to securely store the password, and users of sshpass should consider whether ssh's public key authentication provides the same end-user experience, while involving less hassle and being more secure.
首先,sshpass 的用户应该意识到,ssh 坚持只以交互方式获取密码并非没有道理。安全地存储密码几乎是不可能的,sshpass 的用户应该考虑 ssh 的公钥认证是否提供相同的最终用户体验,同时涉及更少的麻烦和更安全。
So, is it not possible to securely run multiple ssh, scp commands by entering the ssh/ftp password (if only once at runtime? Please read my Requirement section again.
因此,是否无法通过输入 ssh/ftp 密码安全地运行多个 ssh、scp 命令(如果只在运行时一次?请再次阅读我的要求部分。
Also, can anyone explain this -
另外,谁能解释一下-
In particular, people writing programs that satisfies are meant to communicate the above points)password programatically are encouraged to use an anonymous pipe and pass the pipe's reading end to sshpass using the -d option.
特别是,编写满足以上几点的程序的人鼓励以编程方式使用密码,并使用 -d 选项将管道的读取端传递给 sshpass。
Does this mean anything is possible?
这是否意味着一切皆有可能?
回答by Marty Neal
Indeed, you'll definitely want to look into setting up ssh keys, over saving a password in a bash script. If the key is passwordless, then no user input will be required to ssh/scp. You just set it up to use the key on both ends and voila, secured communication.
确实,您肯定希望研究设置 ssh 密钥,而不是在 bash 脚本中保存密码。如果密钥是无密码的,则 ssh/scp 不需要用户输入。您只需将其设置为在两端使用密钥,即可实现安全通信。
However, I'll get downvoted to hell if I don't say this. Many consider passwordless ssh keys to be a Bad Idea(TM). If anybody gets their hands on the keys, the have full access. This means that you are relying on other security measures such as file permissions to keep your password safe.
但是,如果我不说这个,我会被贬低。许多人认为无密码 ssh 密钥是一个坏主意(TM)。如果有人拿到钥匙,他们就可以完全访问。这意味着您依靠其他安全措施(例如文件权限)来确保密码安全。
Also, look into ssh-agent. It allows you to set it up so that you have a password protected ssh-key, but you only need to type it in once and it will manage the password for the key for you and use it when necessary. On my linux box at home, I have ssh-agent set up to run in my .xinitrc file so that it prompts me once and then starts X. YMMV.
另外,查看 ssh-agent。它允许您设置它,以便您拥有受密码保护的 ssh 密钥,但您只需输入一次,它就会为您管理密钥的密码,并在必要时使用它。在我家里的 linux 机器上,我将 ssh-agent 设置为在我的 .xinitrc 文件中运行,以便它提示我一次然后启动 X. YMMV。
UPDATE:
With regards to your requirements, password protected public key authentication + ssh-agent still seems to fit. Only the developers privy to the SSH/FTP password could start up ssh-agent, type in the password and ssh-agent would manage the passwords for the public keys for the rest of the session, never requiring interaction again.
更新:
关于您的要求,受密码保护的公钥身份验证 + ssh-agent 似乎仍然适合。只有知道 SSH/FTP 密码的开发人员才能启动 ssh-agent,输入密码,然后 ssh-agent 将管理剩余会话的公钥密码,不再需要交互。
Of course, how it stores it is another matter entirely. IANASE, but for more information on security concerns of using ssh-agent, I found symantec's article to be pretty informative: http://www.symantec.com/connect/articles/ssh-and-ssh-agent
当然,它如何存储它完全是另一回事。IANASE,但有关使用 ssh-agent 的安全问题的更多信息,我发现 symantec 的文章非常有用:http: //www.symantec.com/connect/articles/ssh-and-ssh-agent
"The ssh-agent creates a unix domain socket, and then listens for connections from /usr/bin/ssh on this socket. It relies on simple unix permissions to prevent access to this socket, which means that any keys you put into your agent are available to anyone who can connect to this socket. [ie. root]" ...
"however, [..] they are only usable while the agent is running -- root could use your agent to authenticate to your accounts on other systems, but it doesn't provide direct access to the keys themselves. This means that the keys can't be taken off the machine and used from other locations indefinitely."
“ssh-agent 创建了一个 unix domain socket,然后在这个 socket 上监听来自 /usr/bin/ssh 的连接。它依赖简单的 unix 权限来阻止访问这个 socket,这意味着你放入代理的任何密钥任何可以连接到此套接字的人都可以使用。[即 root]" ...
“然而,[..] 它们仅在代理运行时可用——root 可以使用您的代理对您在其他系统上的帐户进行身份验证,但它不提供对密钥本身的直接访问。这意味着密钥不能从机器上取下来无限期地从其他地方使用。”
Hopefully you're not in a situation where you're trying to use an untrusted root
's system.
希望您没有遇到尝试使用不受信任root
的系统的情况。
回答by salva
The right way to do that is as follows:
正确的方法如下:
Ensure that all your users are using ssh-agent (nowadays this is the default for most Linux systems). You can check it running the following command:
echo $SSH_AUTH_SOCK
If that variable is not empty, it means that the user is using ssh-agent.
Create a pair of authentication keys for every user ensuring they are protected by a non empty passphrase.
Install the public part of the authentication keys on the remote host so that users can log there.
You are done!
确保您的所有用户都在使用 ssh-agent(现在这是大多数 Linux 系统的默认设置)。您可以运行以下命令来检查它:
回声 $SSH_AUTH_SOCK
如果该变量不为空,则表示用户正在使用 ssh-agent。
为每个用户创建一对身份验证密钥,确保他们受到非空密码的保护。
在远程主机上安装身份验证密钥的公共部分,以便用户可以在那里登录。
你完成了!
Now, the first time an user wants to log into the remote machine from some session it will have to enter the passphrase for its private key.
现在,当用户第一次想从某个会话登录到远程机器时,它必须输入其私钥的密码。
In later logins from the same session ssh-agent will provide the unlocked key for authentication in behalf of the user that will not be required to introduce the passphrase again.
在以后从同一会话登录时,ssh-agent 将代表用户提供解锁密钥以进行身份验证,而无需再次引入密码短语。
回答by Doug A.K.
Ugh. I hit the man pages hard for this. Here's what I got:
啊。为此,我努力阅读手册页。这是我得到的:
Use this code near the beginning of the script to silently get the ssh password:
在脚本开头附近使用此代码以静默方式获取 ssh 密码:
read -p "Password: " -s SSHPASS # *MUST* be SSHPASS
export SSHPASS
And then use sshpass for ssh like so:
然后像这样对 ssh 使用 sshpass:
sshpass -e ssh username@hostname
Hope that helps.
希望有帮助。
回答by chx
You can Using expect to pass a password to sshdo this or as said already use public key authentication instead if that's a viable option.
您可以使用 expect 将密码传递给 ssh执行此操作,或者如上所述,如果这是一个可行的选项,则已使用公钥身份验证。
回答by gsbabil
For password authentication, as you mentioned in you description, you can use "sshpass". On Ubuntu, you can install as "sudo apt-get install sshpass".
对于密码身份验证,正如您在描述中提到的,您可以使用“sshpass”。在 Ubuntu 上,您可以安装为“sudo apt-get install sshpass”。
For public/private key-pair base authentication,
对于公钥/私钥对基本身份验证,
- First generate keys using, "ssh-keygen"
- Then copy your key to the remote machine, using "ssh-copy-id username@remote-machine"
- 首先使用“ssh-keygen”生成密钥
- 然后将您的密钥复制到远程机器,使用“ssh-copy-id username@remote-machine”
Once copied, the subsequent logins should not ask for password.
复制后,后续登录不应要求输入密码。
回答by dietbuddha
Expect is insecure
期望是不安全的
It drives an interactive session. If you were to pass a password via expect it would be no different from you typing a password on the command line exceptthat the expect script would have retrieve the password from somewhere. It's typically insecure because people will put the password in the script, or in a config file.
它驱动一个交互式会话。如果您要通过 expect 传递密码,它与您在命令行上输入密码没有什么不同,只是expect 脚本会从某处检索密码。它通常是不安全的,因为人们会将密码放在脚本或配置文件中。
It's also notoriously brittle because it waits on particular output as the event mechanism for input.
它也是出了名的脆弱,因为它等待特定的输出作为输入的事件机制。
ssh-agent
ssh代理
ssh-agent is a fine solution if this is script that will always be driven manually. If there is someone who will be logged in to drive the execution of the script than an agent is a good way to go. It is not a good solution for automation because an agent implies a session. You usually don't initiate a session to automatically kick of a script (ie. cron).
如果这是始终手动驱动的脚本,ssh-agent 是一个很好的解决方案。如果有人将登录以驱动脚本的执行,那么代理是一个不错的选择。这不是自动化的好解决方案,因为代理意味着会话。您通常不会启动会话来自动启动脚本(即 cron)。
ssh command keys
ssh 命令键
Ssh command keys is your best bet for an automated solution. It doesn't require a session, and the command key restricts what runs on the server to only the command specified in the authorized_keys. They are also typically setup without passwords. This can be a difficult solution to manage if you have thousands of servers. If you only have a few then it's pretty easy to setup and manage.
SSH 命令键是自动化解决方案的最佳选择。它不需要会话,并且命令密钥将服务器上运行的内容限制为仅在authorized_keys 中指定的命令。它们通常也是在没有密码的情况下设置的。如果您有数千台服务器,这可能是一个难以管理的解决方案。如果您只有几个,那么设置和管理非常容易。
service ssh accounts
服务 ssh 帐户
I've also seen setups with password-less service accounts. Instead of the command entry in tehh authorized_keys file, and alternative mechanism is used to restrict access/commands. These solutions often use sudo or restricted shells. However, I think these are more complicated to manage correctly, and therefore tend to be more insecure.
我还看到了无密码服务帐户的设置。代替授权密钥文件中的命令条目,使用替代机制来限制访问/命令。这些解决方案通常使用 sudo 或受限 shell。但是,我认为正确管理这些更复杂,因此往往更不安全。
host to host automatic authentication
主机到主机自动认证
You can also setup host 2 host automatic authentication, but there are alot of things to get write to do this correctly. From setting up your network properly, using a bastion host for host key dissemination, proper ssh server configuration, etc. As a result this is not a solution a recommend unless you know what your doing and have the capacity and ability to set everything up correctly and maintain it as such.
您还可以设置主机 2 主机自动身份验证,但是要正确执行此操作需要进行很多操作。从正确设置网络,使用堡垒主机进行主机密钥分发,正确的 ssh 服务器配置等。因此,除非您知道自己在做什么并且有能力和能力正确设置所有内容,否则这不是推荐的解决方案并保持原样。
回答by vladr
For those for who setting up a keypair is not an option and absolutely need to perform password authentication, use $SSH_ASKPASS
:
对于那些设置密钥对不是一种选择并且绝对需要执行密码身份验证的人,请使用$SSH_ASKPASS
:
SSH_ASKPASS - If ssh needs a passphrase, it will read the passphrase from the current terminal if it was run from a terminal. If ssh does not have a terminal associated with it but DISPLAY and SSH_ASKPASS are set, it will execute the program specified by SSH_ASKPASS and open an X11 window to read the passphrase. This is particularly useful when calling ssh from a .xsession or related script. (Note that on some machines it may be necessary to redirect the input from /dev/null to make this work.)
SSH_ASKPASS - 如果 ssh 需要密码,如果它是从终端运行的,它将从当前终端读取密码。如果 ssh 没有与之关联的终端,但设置了 DISPLAY 和 SSH_ASKPASS,它将执行 SSH_ASKPASS 指定的程序并打开 X11 窗口以读取密码。这在从 .xsession 或相关脚本调用 ssh 时特别有用。(请注意,在某些机器上,可能需要重定向来自 /dev/null 的输入才能使其工作。)
E.g.:
例如:
$ echo <<EOF >password.sh
#!/bin/sh
echo 'password'
EOF
$ chmod 500 password.sh
$ echo $(DISPLAY=bogus SSH_ASKPASS=$(pwd)/password.sh setsid ssh user@host id </dev/null)
See also Tell SSH to use a graphical prompt for key passphrase.
另请参阅告诉 SSH 使用图形提示输入密钥密码。
回答by Thomas Soares
Today, the only way I was able to do this in a bash script via crontab
was like that:
今天,我能够通过 bash 脚本执行此操作的唯一方法是crontab
:
eval $(keychain --eval --agents ssh id_rsa id_dsa id_ed25519)
source $HOME/.keychain/$HOSTNAME-sh
This is with the ssh agent already running and to achieve that it was needed the passphrase.
这是在 ssh 代理已经运行的情况下,并且需要密码短语来实现。
回答by Teddy
Yes, you want pubkey authentication.
是的,您需要公钥身份验证。
回答by aks
ssh
, ssh-keygen
, ssh-agent
, ssh-add
and a correct configuration in /etc/ssh_config
on the remote systems are necessary ingredients for securing access to remote systems.
ssh
、ssh-keygen
、ssh-agent
、ssh-add
和/etc/ssh_config
远程系统上的正确配置是保护对远程系统的访问的必要因素。
First, a private/public keypair needs to be generated with ssh-keygen
. The result of the keygen process are two files: the public keyand the private key.
首先,需要使用ssh-keygen
. 密钥生成过程的结果是两个文件:公钥和私钥。
The public key file, usually stored in ~/.ssh/id_dsa.pub
(or ~/.ssh/id_rsa.pub
, for RSA encryptions) needs to be copied to each remote system that will be granting remote access to the user.
通常存储在~/.ssh/id_dsa.pub
(或~/.ssh/id_rsa.pub
,用于 RSA 加密)的公钥文件需要复制到每个远程系统,这些系统将授予用户远程访问权限。
The private key file should remain on the originating system, or on a portable USB ("thumb") drive that is referenced from the sourcing system.
私钥文件应保留在原始系统上,或保留在源系统引用的便携式 USB(“拇指”)驱动器上。
When generating the key pair, a passphraseis used to protect it from usage by non-authenticated users. When establishing an ssh session for the first time, the private key can only be unlocked with the passphrase. Once unlocked, it is possible for the originating system to remember the unlocked private key with ssh-agent
. Some systems (e.g., Mac OS X) will automatically start up ssh-agent
as part of the login process, and then do an automatic ssh-add -k
that unlocks your private ssh keys using a passphrase previously stored in the keychain file.
生成密钥对时,会使用密码短语来保护它不被未经身份验证的用户使用。首次建立 ssh 会话时,私钥只能通过密码解锁。一旦解锁,原始系统就有可能记住解锁的私钥ssh-agent
。某些系统(例如 Mac OS X)将ssh-agent
作为登录过程的一部分自动启动,然后ssh-add -k
使用先前存储在钥匙串文件中的密码自动解锁您的私人 ssh 密钥。
Connections to remote systems can be direct, or proxied through ssh gateways. In the former case, the remote system only needs to have the public key corresponding to the available unlocked private keys. In the case of using a gateway, the intermediate system must have the public key as well as the eventual target system. In addition, the original ssh command needs to enable agent forwarding, either by configuration in ~/.ssh/config
or by command option -A
.
到远程系统的连接可以是直接的,也可以通过 ssh网关进行代理。在前一种情况下,远程系统只需要拥有与可用的未锁定私钥对应的公钥。在使用网关的情况下,中间系统必须具有公钥以及最终目标系统。另外,原来的ssh命令需要开启代理转发,可以通过配置in~/.ssh/config
或者通过命令option -A
。
For example, to login to remote system "app1" through an ssh gateway system called "gw", the following can be done:
例如,要通过名为“gw”的 ssh 网关系统登录远程系统“app1”,可以执行以下操作:
ssh -At gw ssh -A app1
or the following stanzas placed in the ~/.ssh/config
file:
或放置在~/.ssh/config
文件中的以下节:
Host app1
ForwardAgent = yes
ProxyCommand = ssh -At gw nc %h %p 2>/dev/null
which runs "net cat" (aka nc
) on the ssh gateway as a network pipe.
它nc
在 ssh 网关上作为网络管道运行“net cat”(又名)。
The above setup will allow very simple ssh commands, even through ssh gateways:
上面的设置将允许非常简单的 ssh 命令,即使是通过 ssh 网关:
ssh app1
Sometimes, even more important than terminal sessions are scp
and rsync
commands for moving files around securely. For example, I use something like this to synchronize my personal environment to a remote system:
有时,更重要的是比终端会话scp
及rsync
周边安全地移动文件的命令。例如,我使用这样的东西将我的个人环境同步到远程系统:
rsync -vaut ~/.env* ~/.bash* app1:
Without the config file and nc proxy command, the rsync would get a little more complicated:
如果没有配置文件和 nc proxy 命令,rsync 会变得有点复杂:
rsync -vaut -e 'ssh -A gw' app1:
None of this will work correctly unless the remote systems' /etc/ssh_config
is configured correctly. One such configuration is to remove "root" access via ssh, which improve tracking and accountability when several staff can perform root functions.
除非/etc/ssh_config
正确配置远程系统,否则这些都不会正常工作。一种这样的配置是通过 ssh 删除“root”访问权限,这在多个员工可以执行 root 功能时改进跟踪和问责制。
In unattended batch scripts, a special ssh key-pair needs to be generated for the non-root userid under which the scripts are run. Just as with ssh session management, the batch user ssh key-pair needs to be deployed similarly, with the public key copied to the remote systems, and the private key residing on the source system.
在无人参与的批处理脚本中,需要为运行脚本的非 root 用户 ID 生成一个特殊的 ssh 密钥对。与 ssh 会话管理一样,批处理用户 ssh 密钥对也需要类似地部署,公钥复制到远程系统,私钥驻留在源系统上。
The private key can be locked with a passphrase or unlocked, as desired by the system managers and/or developers. The way to use the special batch ssh key, even in a script running under root, is to use the "ssh -i ~/.ssh/id_dsa
" command options with all remote access commands. For example, to copy a file within a script using the special "batch" user access:
根据系统管理员和/或开发人员的需要,私钥可以用密码锁定或解锁。使用特殊批处理 ssh 密钥的方法,即使是在 root 下运行的脚本中,也是对ssh -i ~/.ssh/id_dsa
所有远程访问命令使用“ ”命令选项。例如,要使用特殊的“批处理”用户访问权限在脚本中复制文件:
rsync -vaut -e 'ssh -i ~batch/.ssh/id_dsa -A gw' $sourcefiles batch@app2:/Sites/www/
This causes rsync
to use a special ssh
command as the remote access shell. The special-case ssh
command uses the "batch" user's DSA private key as its identity. The rsync
command's target remote system will be accessed using the "batch" user.
这导致rsync
使用特殊ssh
命令作为远程访问 shell。特殊情况ssh
命令使用“批处理”用户的 DSA 私钥作为其身份。该rsync
命令的目标远程系统将使用“批量”用户访问。