【问题标题】:Using a variable's value as password for scp, ssh etc. instead of prompting for user input every time使用变量的值作为 scp、ssh 等的密码,而不是每次都提示用户输入
【发布时间】:2011-06-03 10:36:08
【问题描述】:

AFAIK,命令sshscp 没有/带密码参数。否则,我可以将密码保存在 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 密码的开发者能够使用它(所以我猜公钥认证将不起作用,因为它将密码存储在系统中)。

  • 我不想要任何命令行解决方案,它会将密码存储在系统的某个日志中,并且可以使用 ps aux 或其他工具让世界可见。

开放赏金
从到目前为止的所有答案以及我对这些解决方案的分析来看,看起来除了公钥认证之外,其他所有的都是不安全的。我还不确定使用expect 是否不安全。我认为这对我来说是正确的解决方案。在这种情况下,我在尝试执行此操作时遇到命令未找到错误,正如已对其中一个答案发表的评论一样。

来自http://www.debianadmin.com/sshpass-non-interactive-ssh-password-authentication.html -

首先,sshpass 的用户 应该意识到ssh的坚持 仅获取密码 互动不是没有道理的。 几乎不可能 安全地存储密码和用户 sshpass 应该考虑是否 ssh 的公钥认证 提供相同的最终用户体验, 同时涉及更少的麻烦和存在 更安全。

那么,是否可以通过输入 ssh/ftp 密码来安全地运行多个 ssh、scp 命令(如果在运行时只运行一次?请再次阅读我的要求部分。

还有,谁能解释一下这个-

尤其是编写程序的人 满足的意思是 沟通以上几点)密码 鼓励以编程方式使用 匿名管道并通过管道的 使用 -d 读取到 sshpass 选项。

这是否意味着一切皆有可能?

【问题讨论】:

  • 您应该使用ssh-agent 而不是这种非常不安全的方法。
  • sshscp 是外部实用程序,而不是 Bash shell 命令。
  • @İsmail 'cartman' Dönmez - 你能解释一下或给我发一些解释的链接吗?我是 shell 新手,所以不知道如何存储在密码中不太安全。
  • @Sandeepan Nath,见mah.everybody.org/docs/ssh
  • 对不起,我的意思是解释在变量中存储密码是不安全的事实。

标签: bash shell variables ssh


【解决方案1】:

确实,您肯定会想研究设置 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 的安全问题的更多信息,我发现 symantec 的文章信息量很大:http://www.symantec.com/connect/articles/ssh-and-ssh-agent

"ssh-agent 创建一个 unix 域 socket,然后监听 来自 /usr/bin/ssh 的连接 插座。它依赖于简单的unix 阻止访问此的权限 插座,这意味着你的任何键 放入您的代理可用于 任何可以连接到此套接字的人。 [IE。根]" ...

“但是,[..] 它们只能使用 代理运行时 -- root 可以使用您的代理进行身份验证 到您在其他系统上的帐户,但是 它不提供直接访问 钥匙本身。这意味着 钥匙不能从上面取下来 机器并从其他位置使用 无限期。”

希望您没有尝试使用不受信任的root 的系统。

【讨论】:

  • 感谢您的回答。那么,如果我使用 ssh-agent,并且有多个 ssh/scp 命令,我是否只需要输入一次密码?请查看我的更新部分。
  • 自从我在第 1 版回答以来,我的这个问题已经大大增加。抱歉,我花了一段时间才回复你,请参阅我的更新以回应你的问题。
  • “IANASE”是什么意思?
  • @IainElder 这是 I Am Not A Security Expert 的缩写,是 IANAL(我不是律师)短语的变体
  • 我读到“我不是软件工程师”。也许最好只是拼写长:-)
【解决方案2】:

正确的做法如下:

  1. 确保您的所有用户都在使用 ssh-agent(现在这是大多数 Linux 系统的默认设置)。您可以运行以下命令对其进行检查:

    回显 $SSH_AUTH_SOCK

    如果该变量不为空,则表示用户正在使用 ssh-agent。

  2. 为每个用户创建一对身份验证密钥,确保他们受到非空密码的保护。

  3. 在远程主机上安装身份验证密钥的公共部分,以便用户可以在那里登录。

  4. 你完成了!

现在,用户第一次想从某个会话登录远程计算机时,必须输入其私钥的密码。

在以后从同一会话登录时,ssh-agent 将代表用户提供解锁密钥进行身份验证,无需再次输入密码。

【讨论】:

  • 您能否使用第 2 步和第 3 步的资源和代码改进此答案。
【解决方案3】:

呃。为此,我很难找到手册页。这是我得到的:

在脚本开头附近使用此代码以静默获取 ssh 密码:

read -p "Password: " -s SSHPASS # *MUST* be SSHPASS
export SSHPASS

然后像这样对 ssh 使用 sshpass:

sshpass -e ssh username@hostname

希望对您有所帮助。

【讨论】:

  • 这样做密码以后不能使用ps aux查看?
  • ps aux 无法查看。它也不在 bash 历史中。
  • 感谢您的确认。我会试试这个,让你知道。
  • 如果您部署此解决方案,请尝试ps auxwe | grep SSHPASS -- ps 将愉快地从程序中读取环境变量。我不了解你,但我不希望 Firefox 读取我的 ssh 通行证。使用公钥和 ssh-agent。
【解决方案4】:

如果可行的话,您可以 Using expect to pass a password to ssh 执行此操作,或者如前所述使用公钥身份验证。

【讨论】:

  • 对于像我这样的新手,这里是对公钥认证如何工作的解释 - spy-hill.com/~myers/help/PublicKey.html(在第一段中解释)。
  • 感谢您的回答和 cmets @chx 和 @glenn jackman。请检查我有问题的更新。
  • @chx - 我收到“找不到命令”错误,例如 spawn: command not foundexpect: command not found 等。
  • 我已经为此stackoverflow.com/questions/4612937/…提出了一个单独的问题
  • 使用 Expect 来保存和传递 ssh 密码是不安全、脆弱且非常糟糕的做法。仅当您了解成本将是多少时才这样做,并且没有其他方法可以做到。
【解决方案5】:

对于密码验证,正如您在描述中提到的,您可以使用“sshpass”。在 Ubuntu 上,您可以安装为“sudo apt-get install sshpass”。

对于公钥/私钥对基础身份验证,

  • 首先使用“ssh-keygen”生成密钥
  • 然后使用“ssh-copy-id username@remote-machine”将您的密钥复制到远程计算机

复制后,后续登录不应要求输入密码。

【讨论】:

  • debianadmin.com/… 表示“安全存储密码几乎是不可能的,sshpass 的用户应该考虑 ssh 的公钥认证是否提供相同的最终用户体验,同时涉及更少的麻烦和被更安全。”所以看起来 sshpass 也遇到了这个问题(比如期望脚本)
【解决方案6】:

预期不安全

它驱动一个交互式会话。如果您要通过 expect 传递密码,这与您在命令行上输入密码没有什么不同除了,expect 脚本会从某个地方检索密码。这通常是不安全的,因为人们会将密码放在脚本或配置文件中。

它也是出了名的脆弱,因为它等待特定的输出作为输入的事件机制。

ssh 代理

ssh-agent 是一个很好的解决方案,如果这是始终手动驱动的脚本。如果有人将登录以驱动脚本的执行,那么代理是一个不错的方法。这不是一个很好的自动化解决方案,因为代理意味着会话。您通常不会启动会话来自动启动脚本(即 cron)。

ssh 命令键

Ssh 命令键是自动化解决方案的最佳选择。它不需要会话,并且命令密钥将在服务器上运行的内容限制为仅在 authorized_keys 中指定的命令。它们通常也是在没有密码的情况下设置的。如果您有数千台服务器,这可能是一个难以管理的解决方案。如果您只有几个,那么设置和管理非常容易。

服务 ssh 帐户

我还看到了使用无密码服务帐户的设置。而不是 tehh authorized_keys 文件中的命令条目,而是使用替代机制来限制访问/命令。这些解决方案通常使用 sudo 或受限 shell。但是,我认为正确管理这些更复杂,因此往往更不安全。

主机到主机自动身份验证

您还可以设置主机 2 主机自动身份验证,但要正确执行此操作需要写入很多内容。从正确设置网络、使用堡垒主机进行主机密钥分发、正确的 ssh 服务器配置等。因此,除非您知道自己在做什么并且有能力和能力正确设置所有内容,否则这不是推荐的解决方案并保持原样。

【讨论】:

    【解决方案7】:

    对于那些无法设置密钥对并且绝对需要执行密码验证的用户,请使用$SSH_ASKPASS

    SSH_ASKPASS - 如果 ssh 需要密码,如果它是从终端运行的,它将从当前终端读取密码。如果 ssh 没有与之关联的终端,但设置了 DISPLAY 和 SSH_ASKPASS,它将执行 SSH_ASKPASS 指定的程序并打开 X11 窗口以读取密码。这在从 .xsession 或相关脚本调用 ssh 时特别有用。 (请注意,在某些机器上,可能需要从 /dev/null 重定向输入以使其工作。)

    例如:

    $ 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)
    

    另见Tell SSH to use a graphical prompt for key passphrase

    【讨论】:

      【解决方案8】:

      是的,您需要公钥身份验证。

      【讨论】:

        【解决方案9】:

        今天,我能够通过 crontab 在 bash 脚本中执行此操作的唯一方法是:

        eval $(keychain --eval --agents ssh id_rsa id_dsa id_ed25519)
        source $HOME/.keychain/$HOSTNAME-sh
        

        这是因为 ssh 代理已经在运行,并且需要密码。

        【讨论】:

          【解决方案10】:

          sshssh-keygenssh-agentssh-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命令需要开启代理转发,可以通过~/.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
          

          有时,比终端会话更重要的是用于安全移动文件的scprsync 命令。例如,我使用这样的东西将我的个人环境同步到远程系统:

          rsync -vaut ~/.env* ~/.bash* app1:
          

          如果没有配置文件和 nc 代理命令,rsync 会变得有点复杂:

          rsync -vaut -e 'ssh -A gw' app1:
          

          除非远程系统的/etc/ssh_config 配置正确,否则这些都不会正常工作。一种这样的配置是通过 ssh 删除“root”访问权限,这可以在多个员工可以执行 root 功能时改进跟踪和问责制。

          在无人值守的批处理脚本中,需要为运行脚本的非 root 用户 ID 生成一个特殊的 ssh 密钥对。与 ssh 会话管理一样,批量用户 ssh 密钥对也需要类似地部署,将公钥复制到远程系统,并将私钥保存在源系统上。

          可以根据系统管理员和/或开发人员的需要,使用密码锁定或解锁私钥。使用特殊批处理 ssh 密钥的方法,即使在 root 下运行的脚本中,也是对所有远程访问命令使用“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 命令使用“batch”用户的DSA 私钥作为其身份。 rsync 命令的目标远程系统将使用“batch”用户访问。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-02-15
            • 2019-07-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多