AFAIK,命令ssh
或scp
没有/接受密码参数。否则我可以将密码保存在shell变量中,并可能摆脱输入密码提示。如果我在shell脚本中编写scp命令,则会提示用户输入密码。我的脚本中有多个ssh和scp命令,我不希望用户每次都输入密码。我更喜欢在开头的shell变量中保存密码(通过询问密码一次),然后将其用于每个ssh或scp。
我在this question中读到了“公钥识别”。它与我正在寻找的解决方案有关吗?
更新
我在How to use ssh command in shell script?中读到为什么在命令行上指定密码是不安全的。使用expect
是否也存储密码并且是世界可见的(使用ps aux
)?这是使用expect
的安全问题吗?
进一步说明
为了进一步说清楚,我正在编写这个shell脚本来自动执行代码和数据库备份,执行代码上载,运行必要的数据库查询,从开发人员那里完成LAMP project的新版本所需的所有操作系统到远程实时服务器。我的shell脚本将存在于每个开发人员实例中项目的主代码库中。
要求
我希望所有开发人员(都可能在不同的远程系统工作)知道SSH / FTP密码,只能在运行时输入一次ssh / ftp密码才能使用shell。我更希望密码是ssh / ftp密码
注意 - 我不希望其他不知道SSH密码的开发人员能够使用它(所以我猜公钥验证不起作用,因为它将密码存储在系统中)。
开放赏金
从目前为止的所有答案以及我对这些解决方案的分析来看,除了公钥认证之外,其他所有其他都是不安全的。我还不确定使用expect
是不安全的。我认为这对我来说是正确的解决方案。在这种情况下,我在尝试执行此操作时遇到命令未找到错误,因为已经对其中一个答案进行了评论。
来自http://www.debianadmin.com/sshpass-non-interactive-ssh-password-authentication.html -
首先是sshpass的用户 应该意识到ssh的坚持 仅获取密码 交互式并非没有道理。 这几乎是不可能的 安全地存储密码和用户 sshpass应该考虑是否 ssh的公钥认证 提供相同的最终用户体验, 虽然涉及较少的麻烦和存在 更安全。
那么,是不是可以通过输入ssh / ftp密码安全地运行多个ssh,scp命令(如果只在运行时一次?请再次阅读我的需求部分。
此外,任何人都可以解释这个 -
特别是人们编写程序 满足意味着 沟通以上几点)密码 以编程方式鼓励使用 一个匿名管道并传递管道 使用-d读取sshpass的结尾 选项。
这是否意味着什么是可能的?
答案 0 :(得分:8)
事实上,你肯定想要研究设置ssh密钥,而不是在bash脚本中保存密码。如果密钥是无密码的,则ssh / scp不需要用户输入。您只需将其设置为在两端使用密钥,然后保护通信。
然而,如果我不这样说的话,我会陷入地狱。许多人认为无密码ssh密钥是Bad Idea(TM)。如果有人拿到钥匙,那么就可以完全进入。这意味着您依赖其他安全措施(如文件权限)来保护您的密码安全。
另外,请查看ssh-agent。它允许您进行设置,以便您拥有受密码保护的ssh-key,但您只需要输入一次,它将为您管理密钥的密码并在必要时使用它。在我家的linux机器上,我设置ssh-agent在我的.xinitrc文件中运行,这样它就会提示我一次,然后启动X. YMMV。
<强>更新强>
关于您的要求,密码保护的公钥认证+ ssh-agent似乎仍然适合。只有熟悉SSH / FTP密码的开发人员才能启动ssh-agent,输入密码,ssh-agent将管理会话其余部分的公钥密码,不再需要再次进行交互。
当然,它如何存储它完全是另一回事。 IANASE,但是有关使用ssh-agent的安全问题的更多信息,我发现赛门铁克的文章非常有用:http://www.symantec.com/connect/articles/ssh-and-ssh-agent
“ssh-agent创建一个unix域 socket,然后监听 来自/ usr / bin / ssh的连接 插座。它依赖于简单的unix 权限,以防止访问此权限 socket,这意味着任何键你 放入您的代理商可用 任何可以连接到此套接字的人。 [即。 root]“......
“然而,[..]它们只能使用 代理运行时 - 根 可以使用您的代理进行身份验证 到您在其他系统上的帐户,但是 它不提供直接访问 钥匙本身。这意味着 钥匙不能脱掉 机器和从其他地方使用 无限期“。
希望您没有尝试使用不受信任的root
系统。
答案 1 :(得分:6)
正确的方法如下:
确保所有用户都使用ssh-agent(现在这是大多数Linux系统的默认设置)。您可以检查它是否运行以下命令:
echo $ SSH_AUTH_SOCK
如果该变量不为空,则表示该用户正在使用ssh-agent。
为每个用户创建一对身份验证密钥,确保它们受非空密码短语的保护。
在远程主机上安装公共部分身份验证密钥,以便用户可以登录。
你已经完成了!
现在,用户第一次想要从某个会话登录远程计算机时,必须输入其私钥的密码。
在以后的同一会话登录中,ssh-agent将代表用户提供解锁密钥以进行身份验证,而不需要再次引入密码。
答案 2 :(得分:3)
您可以Using expect to pass a password to ssh执行此操作,或者如果这是可行的选项,则可以使用公钥认证。
答案 3 :(得分:3)
唉。我为此努力了。这就是我得到的:
在脚本开头附近使用此代码以静默方式获取ssh密码:
read -p "Password: " -s SSHPASS # *MUST* be SSHPASS
export SSHPASS
然后像ssh一样使用sshpass:
sshpass -e ssh username@hostname
希望有所帮助。
答案 4 :(得分:2)
对于密码验证,如您在说明中所述,您可以使用“sshpass”。在Ubuntu上,您可以安装为“sudo apt-get install sshpass”。
对于公钥/私钥对基本身份验证,
复制后,后续登录不应要求输入密码。
答案 5 :(得分:2)
期待不安全
它驱动一个交互式会话。如果您通过密码传递密码,那么在命令行上键入密码与之外的密码没有什么不同,期望脚本会从某个地方检索密码。它通常是不安全的,因为人们会将密码放在脚本中或配置文件中。
它也是众所周知的脆弱因为它等待特定输出作为输入的事件机制。
<强> SSH剂强>
如果这是一个总是手动驱动的脚本,那么ssh-agent是一个很好的解决方案。如果有人将登录以驱动脚本的执行,那么代理是一个很好的方法。它不是一个很好的自动化解决方案,因为代理意味着一个会话。您通常不会启动会话以自动启动脚本(即.cron)。ssh命令键
Ssh命令键是自动解决方案的最佳选择。它不需要会话,并且命令键将服务器上运行的内容限制为仅在authorized_keys中指定的命令。它们通常也没有密码设置。如果您有数千台服务器,这可能是一个难以管理的解决方案。如果您只有一些,那么设置和管理非常简单。
服务ssh帐户
我还看到了使用无密码服务帐户的设置。而不是使用tehh authorized_keys文件中的命令条目,而是使用替代机制来限制访问/命令。这些解决方案通常使用sudo或限制shell。但是,我认为正确管理这些更复杂,因此往往更不安全。
托管主机自动身份验证
您还可以设置主机2主机自动身份验证,但要正确执行此操作,还有很多事情需要编写。从正确设置网络,使用堡垒主机进行主机密钥传播,正确的ssh服务器配置等。因此,这不是推荐的解决方案,除非您知道自己在做什么,并且具备正确设置所有内容的能力和能力并保持原样。
答案 6 :(得分:1)
是的,您需要进行pubkey身份验证。
答案 7 :(得分:1)
对于那些设置密钥对不是一个选项且绝对需要执行密码身份验证的人,请使用$SSH_ASKPASS
:
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)
答案 8 :(得分:1)
今天,我通过crontab
在bash脚本中执行此操作的唯一方法就是:
eval $(keychain --eval --agents ssh id_rsa id_dsa id_ed25519)
source $HOME/.keychain/$HOSTNAME-sh
这是因为ssh代理已在运行,并且需要密码才能实现。
答案 9 :(得分:0)
ssh
,ssh-keygen
,ssh-agent
,ssh-add
以及远程系统/etc/ssh_config
中的正确配置是保护远程系统访问安全的必要因素。
首先,需要使用ssh-keygen
生成私人/公共密钥对。密钥生成过程的结果是两个文件:公钥和私钥。
通常存储在~/.ssh/id_dsa.pub
(或~/.ssh/id_rsa.pub
中,用于RSA加密)的公钥文件需要复制到将授予用户远程访问权限的每个远程系统。
私钥文件应保留在原始系统上,或保留在从采购系统引用的便携式USB(“拇指”)驱动器上。
生成密钥对时,密码短语用于保护其免受未经过身份验证的用户的使用。在第一次建立ssh会话时,只能使用密码解锁私钥。解锁后,原始系统可以使用ssh-agent
记住解锁的私钥。某些系统(例如,Mac OS X)将在登录过程中自动启动ssh-agent
,然后执行自动ssh-add -k
,使用先前存储在钥匙串文件。
与远程系统的连接可以是直接连接,也可以通过ssh 网关进行代理。在前一种情况下,远程系统仅需要具有与可用的未锁定私钥对应的公钥。在使用网关的情况下,中间系统必须具有公钥以及最终目标系统。此外,原始ssh命令需要通过~/.ssh/config
中的配置或命令选项-A
启用代理转发。
例如,要通过名为“gw”的ssh网关系统登录远程系统“app1”,可以执行以下操作:
ssh -At gw ssh -A app1
或以下节放在~/.ssh/config
文件中:
Host app1
ForwardAgent = yes
ProxyCommand = ssh -At gw nc %h %p 2>/dev/null
在ssh网关上运行“net cat”(又名nc
)作为网络管道。
上面的设置将允许非常简单的ssh命令,即使是通过ssh网关:
ssh app1
有时,比终端会话更重要的是scp
和rsync
命令,用于安全地移动文件。例如,我使用类似的东西将我的个人环境同步到远程系统:
rsync -vaut ~/.env* ~/.bash* app1:
如果没有配置文件和nc proxy命令,rsync会变得更加复杂:
rsync -vaut -e 'ssh -A gw' app1:
除非正确配置远程系统“/etc/ssh_config
,否则这些都不会正常工作。其中一种配置是通过ssh删除“root”访问权限,这可以在多名员工执行root功能时改进跟踪和责任。
在无人参与的批处理脚本中,需要为运行脚本的非root用户标识生成特殊的ssh密钥对。与ssh会话管理一样,批处理用户ssh密钥对需要以类似方式部署,公钥复制到远程系统,私钥驻留在源系统上。
根据系统管理员和/或开发人员的需要,可以使用密码锁定私钥或解锁私钥。即使在root下运行的脚本中,使用特殊批处理ssh密钥的方法是对所有远程访问命令使用“ssh -i ~/.ssh/id_dsa
”命令选项。例如,使用特殊的“批处理”用户访问权限复制脚本中的文件:
rsync -vaut -e 'ssh -i ~batch/.ssh/id_dsa -A gw' $sourcefiles batch@app2:/Sites/www/
这会导致rsync
使用特殊的ssh
命令作为远程访问shell。特殊情况ssh
命令使用“批处理”用户的DSA私钥作为其标识。将使用“批处理”用户访问rsync
命令的目标远程系统。