在ssh上进行sudo的正确方法


150

我有一个脚本,该脚本使用sudo在远程服务器上通过SSH运行另一个脚本。但是,当我键入密码时,它会显示在终端上。(否则效果很好)

ssh user@server "sudo script"

这样做的正确方法是什么,这样我可以通过SSH输入sudo的密码,而键入时却不会出现密码?


2
对我而言,寻找通过ssh进行冲洗的方法的原因是,尝试进行类似操作时它不起作用ssh <user@server> sudo <script>,因为我遇到了错误sudo: no tty present and no askpass program specified
knocte

Answers:


244

另一种方法是使用-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.

2
很好,我知道-t选项,只是不知道它适用于sudo提示。

3
-t选项有什么用?
文斯2014年


3
它在这里不起作用: ssh -t localhost <<< "sudo touch file;"编辑显然,将命令作为参数而不是通过标准输入提供是很重要的(事后看来很有意义)。
限量赎罪

-t方法还将显示正常情况下命令的彩色输出。
karmakaze

24

我可以使用以下命令将其完全自动化:

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

优点:

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

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


6
它将显示在本地系统的bash历史记录中,包括密码。最好将密码存储在文件中并整理文件。
Kurt Fitzner

4
伙计,我知道了-t,但是我没有足够仔细地阅读该手册,以至于您可以通过两次!这就是我几个月以来一直在寻找的东西为了增加安全性,我只需在与一起运行之前设置一个密码变量read -s -p "Password: " pw,然后再进行操作即可echo "$pw" | ....。我现在将其自己打包成一个方便的脚本:)。
kael

对我来说就像魅力!
MiKr13

您为什么不为需要运行的任何特定用户和命令设置无密码sudo?这不是SSH问题...
nomen

@nomen您的解决方案也是有效的,但需要额外的步骤。如果我有很多没有无密码sudo用户的设备,则可以使用此解决方案创建自动化脚本。有时,您在不拥有的系统上工作,不希望或无法进行更改,有时还需要考虑其他因素。
ofirule

6

假设您不希望输入密码提示

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

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

13
这很危险,因为明文密码以命令行结尾。命令行是公共的,并且可以被系统上的所有其他用户和进程看到。例如,非特权用户的“ ps auxwwwww”将显示正在运行的每个进程以及运行它们的命令行。
Kurt Fitzner '18

3
更不用说将您的密码(以纯文本格式)放入bash_history文件中。
Layne Bernardo

4

通过SSH的Sudo传递密码,不需要tty:

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

示例1-简单的远程命令

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

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

我们告诉sudo不要发出提示,而要从stdin接受输入。这使sudo密码传递完全安静,因此您返回的唯一响应是的输出whoami

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

示例2-需要自己的stdin的远程命令

在下面的示例中,远程命令“ cat”是通过sudo执行的,我们通过stdin提供了一些额外的行来显示远程cat。

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

输出表明该<remote_sudo_password>行已被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

应该注意的是,在以上所有命令行示例中(除了脚本之外<< 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 remote命令中,为什么需要执行cat并将结果通过管道传输到sudo中?您可以仅用sudo作ssh的主要远程命令吗?
joanpau

@joanpau缩写词cat用于将用户密码通过管道传递到另一侧的sudo。如果用户可以在没有密码的情况下运行sudo,则不是必需的,但我不建议这种配置。用管道传输的原因是为了防止密码显示在远程系统的命令行上。命令行不安全,任何用户都可以使用来查看每个命令行ps auxwww
Kurt Fitzner '19

cat在ssh命令中要求cat \| sudo --prompt="" -S...。如果-S强行sudo从stdin读取密码,那么猫和烟斗根本没有必要吗?ssh命令可以简单sudo --prompt="" -S...吗?
joanpau

@jonpau该cat命令正在使用stdin并将其通过sudo传递给sudo密码。它显示了如何通过stdin安全地通过ssh通过ssh传递sudo密码。
Kurt Fitzner,

1

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

希望它能帮助您消除疑虑。




-1

我遇到了一个问题

user1@server1$ ssh -q user1@server2 sudo -u user2 rm -f /some/file/location.txt

Output:
sudo: no tty present and no askpass program specified

然后我尝试了

#1
vim /etc/sudoers
Defaults:user1    !requiretty

没用

#2
user1   ALL=(user2)         NOPASSWD: ALL

正常工作!


这并不能真正完成所要求的。这个想法是仍然需要密码,但是允许通过ssh输入密码。您所做的只是授予了user1对user2的完全sudo访问权限,而无需输入密码。这对特定的应用程序来说很好,但是作为一般解决方案并不是最好的主意。
Possum

-7

根据您的使用情况,我在以下方面取得了成功:

ssh root@server "script"

这将提示您输入root密码,然后正确执行命令。


24
kes,SSH是root?由于种种原因,这是一个坏主意。
darkfeline 2013年

11
记住ssh不是telnet。以root身份使用ssh并没有比以其他用户身份使用ssh并运行sudo更危险。您的密码通过ssh连接以相同的方式加密。
斯特凡2014年

21
就密码安全性而言,Stéphane是绝对正确的。但是,通过使用root而不是sudo,您将失去sudo附带的审核跟踪。此外,root用户访问权限可能不可用。
djeikyb 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.