正如评论中已经提到的,最安全的方法是使用 CreateShellStream 并在运行 sudo 命令后将密码直接写入流。密码的发送就像您使用交互式终端一样。但是,如果您不想被锁定使用无尽的流来完成您想做的其余事情,那么这可能不是一个方便的解决方案。例子:
var promptRegex = new Regex(@"\][#$>]"); // regular expression for matching terminal prompt
var modes = new Dictionary<Renci.SshNet.Common.TerminalModes, uint>();
using (var stream = ssh.CreateShellStream("xterm", 255, 50, 800, 600, 1024, modes))
{
stream.Write("sudo iptables -L -n\n");
stream.Expect("password");
stream.Write("mypassword\n");
var output = stream.Expect(promptRegex);
}
缺点是您的输出将包含您并不真正想要的垃圾:控制字符、提示以及通过流发送的所有其他内容。
如果您想避免使用 shell 流,那么您可以(取决于安全设置)通过 stdin 提供密码。这是不安全的,因为命令会记录在不同的地方,并且您可能会向其他具有 root 访问权限的用户泄露您的密码。如果您是唯一的用户,或者您不关心其他人可以看到您的密码,那么这对您来说可能会更方便。
Example:
using (var cmd = ssh.RunCommand("echo -e 'mypassword\n' | sudo -S iptables -L -n"))
{
if (cmd.ExitStatus == 0)
Console.WriteLine(cmd.Result);
else
Console.WriteLine(cmd.Error);
}
最后,还可以让脚本将您的密码打印到标准输入。这样您的密码就不会与命令行的其余部分一起被记录;但这仍然不够安全,因为具有 root 访问权限的任何人都可能读取脚本并查看密码:
using (var cmd = ssh.RunCommand("~/printpasswd.sh | sudo -S iptables -L -n"))
{
if (cmd.ExitStatus == 0)
Console.WriteLine(cmd.Result);
else
Console.WriteLine(cmd.Error);
}
和 printpasswd.sh 内部:
#!/bin/bash
echo -e 'mypassword\n'