【问题标题】:proper way to sudo over ssh通过 ssh 进行 sudo 的正确方法
【发布时间】:2012-05-05 19:42:13
【问题描述】:

我有一个脚本,它使用 sudo 在远程服务器上通过 SSH 运行另一个脚本。但是,当我输入密码时,它会显示在终端上。 (否则它工作正常)

ssh user@server "sudo script"

执行此操作的正确方法是什么,以便我可以通过 SSH 键入 sudo 的密码,而不会在我键入时出现密码?

【问题讨论】:

  • 对我来说,寻找一种通过 ssh 进行 sudo 的方法的原因是,在尝试类似 ssh <user@server> sudo <script> 时它不起作用,因为我收到了错误 sudo: no tty present and no askpass program specified

标签: ssh sudo


【解决方案1】:

NOPASS 在您的目标机器上的配置是解决方案。继续阅读http://maestric.com/doc/unix/ubuntu_sudo_without_password

【讨论】:

  • 在这种情况下,我实际上想要一个密码,并直接输入它,所以这对我不起作用。
【解决方案2】:

另一种方法是使用-t 切换到ssh

ssh -t user@server "sudo script"

man ssh:

 -t      Force pseudo-tty allocation.  This can be used to execute arbi-
         trary screen-based programs on a remote machine, which can be
         very useful, e.g., when implementing menu services.  Multiple -t
         options force tty allocation, even if ssh has no local tty.

【讨论】:

  • 很好,我知道 -t 选项,只是不知道它适用于 sudo 提示。
  • -t 选项有什么用?
  • 它在这里不起作用:ssh -t localhost <<< "sudo touch file;" 编辑显然,重要的是您实际提供命令作为参数,而不是通过标准输入(事后看来这很有意义)。
  • -t 方法还将显示通常执行此操作的命令的彩色输出。
【解决方案3】:

最好的方法是ssh -t user@server "sudo <scriptname>",例如ssh -t user@server "sudo reboot"。 它会先提示用户输入密码,然后是 root(因为我们正在以 root 权限运行脚本或命令。

我希望它可以帮助并消除您的疑问。

【讨论】:

    【解决方案4】:

    假设您不需要密码提示

    ssh $HOST 'echo $PASSWORD | sudo -S $COMMMAND'
    

    例子

    ssh me@localhost 'echo secret | sudo -S echo hi' # outputs 'hi'
    

    【讨论】:

    • 这是 /very/ 危险的,因为明文密码最终出现在命令行上。命令行是公共的,系统上的每个其他用户和进程都可以看到。例如,非特权用户的“ps auxwwwww”将显示 每个 正在运行的进程以及运行它们的命令行。
    • 更不用说将您的密码(以明文形式)放入 bash_history 文件中。
    • 根据您的 shell 配置(默认在 bash 中),在命令跳过将其添加到历史记录之前放置一个空格。您也可以保留 $PASSWORD 并在之前执行以空格为前缀的 `export PASSWORD=secret`。只需确保在不让 env var 闲逛之后退出会话。
    • 另外,你可以让 bash 历史记录不记录任何带有特定字符串的命令,我已经禁止存储任何 export 命令以避免任何重要的令牌或秘密在那里结束
    【解决方案5】:

    我能够使用以下命令完全自动化它:

    echo pass | ssh -tt user@server "sudo script"
    

    优点:

    • 没有密码提示
    • 不会在远程计算机 bash 历史记录中显示密码

    关于安全性:正如Kurt所说,运行此命令将在本地bash历史记录中显示您的密码,最好将密码保存在不同的文件中或将所有命令保存在一个.sh 文件并执行它。注意:该文件需要具有正确的权限,以便只有允许的用户才能访问它。

    【讨论】:

    • 它将显示在本地系统的 bash 历史记录中,包括密码。最好将密码存储在文件中并将文件分类。
    • 伙计,我知道-t,但我没有仔细阅读手册,看​​你可以通过两次!这就是我 个月以来一直在寻找的东西! 作为安全补充,我只是在运行 read -s -p "Password: " pw 之前设置了一个密码变量,然后使用了 echo "$pw" | ....。我现在已经为自己把它变成了一个方便的脚本:)。
    • 对我来说很有魅力!
    • 您为什么不为您需要运行的任何特定用户和命令设置无密码 sudo?这不是 SSH 问题...
    • 关于防止密码出现在本地历史中,1)如果它是脚本中的一行,这不是问题,2)对于 interactive shell,本地历史很容易避免如果HISTCONTROL 设置为ignorespaceignoreboth(假设为bash,其他shell 类似),则以空格开头命令。另一个安全问题是密码可能会显示在进程表中。 echo 通常是内置的 shell,所以它可能是 OK,但我宁愿使用 here-string<<< pass
    【解决方案6】:

    Sudo over SSH 传递密码,不需要 tty:

    您可以在 ssh 上使用 sudo,而无需强制 ssh 具有伪 tty(不使用 ssh“-t”开关),方法是告诉 sudo 不需要交互式密码并从标准输入中获取密码。您可以使用 sudo 上的“-S”开关来执行此操作。这使得 sudo 在标准输入上侦听密码,并在看到换行时停止侦听。

    示例 1 - 简单的远程命令

    在这个例子中,我们发送一个简单的whoami 命令:

    $ ssh user@server cat \| sudo --prompt="" -S -- whoami << EOF
    > <remote_sudo_password>
    root
    

    我们告诉 sudo 不要发出提示,并从标准输入中获取输入。这使得 sudo 密码完全静默传递,因此您得到的唯一响应是来自 whoami 的输出。

    这种技术的好处是允许您通过 sudo 通过 ssh 运行程序,这些程序本身需要标准输入。这是因为 sudo 在 stdin 的第一行使用密码,然后让它运行的任何程序继续获取 stdin。

    示例 2 - 需要自己的标准输入的远程命令

    在以下示例中,远程命令“cat”是通过 sudo 执行的,我们通过标准输入提供了一些额外的行供远程 cat 显示。

    $ ssh user@server cat \| sudo --prompt="" -S -- "cat" << EOF
    > <remote_sudo_password>
    > Extra line1
    > Extra line2
    > EOF
    Extra line1
    Extra line2
    

    输出表明 &lt;remote_sudo_password&gt; 行正在被 sudo 使用,并且远程执行的 cat 正在显示额外的行。

    如果您想使用 ssh 在不使用命令行的情况下将密码传递给特权命令,这将是有益的一个示例。比如说,如果你想通过 ssh 挂载一个远程加密容器。

    示例 3 - 安装远程 VeraCrypt 容器

    在这个示例脚本中,我们通过 sudo 远程挂载 VeraCrypt 容器,没有任何额外的提示文本:

    #!/bin/sh
    ssh user@server cat \| sudo --prompt="" -S -- "veracrypt --non-interactive --stdin --keyfiles=/path/to/test.key /path/to/test.img /mnt/mountpoint" << EOF
    SudoPassword
    VeraCryptContainerPassword
    EOF
    

    需要注意的是,在上述所有命令行示例(除脚本之外的所有内容)中,命令行上的&lt;&lt; EOF 构造将导致键入的所有内容(包括密码)记录在本地 机器的 .bash_history。因此,强烈建议您在实际使用时完全通过脚本来完成,如上面的 veracrypt 示例,或者,如果在命令行上,则将密码放入文件并通过 ssh 重定向该文件。

    示例 1a - 没有本地命令行密码的示例 1

    第一个例子因此变成:

    $ cat text_file_with_sudo_password | ssh user@server cat \| sudo --prompt="" -S -- whoami
    root
    

    示例 2a - 没有本地命令行密码的示例 2

    第二个例子会变成:

    $ cat text_file_with_sudo_password - << EOF | ssh va1der.net cat \| sudo --prompt="" -S -- cat
    > Extra line1
    > Extra line2
    > EOF
    Extra line1
    Extra line2
    

    如果您将整个内容放在脚本中,则无需将密码放在单独的文件中,因为脚本的内容不会最终出现在您的历史记录中。不过,如果您想允许不应该看到密码的用户执行脚本,它仍然很有用。

    【讨论】:

    • 在ssh远程命令中,为什么需要执行cat并将结果通过管道传递给sudo?你能用sudo作为主要的ssh远程命令吗?
    • @joanpau 初始的cat 用于将用户的密码通过管道传递到另一端的sudo。如果用户可以在没有密码的情况下运行 sudo,那么它不是必需的,但我不建议这种配置。它被管道化的原因是为了防止密码出现在远程系统的命令行上。命令行不安全,任何用户都可以看到每个带有ps auxwww的命令行。
    • 我在 ssh 命令cat \| sudo --prompt="" -S... 中要求cat。如果-S 强制sudo 从标准输入读取密码,那么 cat 和 pipe 是否必要? ssh 命令可以简单地是sudo --prompt="" -S...吗?
    • @jonpau 该 cat 命令正在获取标准输入并通过 sudo 进行管道传输,以便将 sudo 密码传递给它。它展示了如何通过标准输入安全地通过 ssh 传输 sudo 密码。
    • cat text_file_with_sudo_password | ssh user@server "cat - | sudo --prompt='' -S -- 'whoami' " 我需要使用“-”或者让 cat 不带参数来接收来自标准输入的输入,至少在 MacOS 上是这样。
    【解决方案7】:
    echo $VAR_REMOTEROOTPASS | ssh -tt -i $PATH_TO_KEY/id_mykey $VAR_REMOTEUSER@$varRemoteHost 
    echo \"$varCommand\" | sudo bash
    

    【讨论】:

    • ...请为您的代码提供解释。
    【解决方案8】:

    确认@ofirule 的答案就像一个魅力。 我什至尝试使用sshpass 并且它有效。这是与 sshpass 一起使用的方法:

    echo $pass | sshpass -p $pass ssh -tt cloud_user@$ip "sudo su -"
    

    你会发现自己直接在 root shell 中

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-30
      • 2021-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多