如何通过sudo运行命令并通过ssh .net c输入密码#

时间:2017-01-09 19:37:13

标签: c# linux ssh ssh.net

我想运行命令并在具有Linux操作系统的远程计算机上获得结果。我使用ssh .net库通过C#代码连接。我之前可以连接并运行一些不需要使用“sudo”的命令。但我不知道如何运行需要由sudo运行的命令,因为运行后 - 例如 - “sudo iptables -L -n”我应该输入密码而我不知道如何在执行此操作后输入密码命令。

这是我的代码:

private void connectingToLinuxHost(string ip, string username, string password, int port)
{
    SshCommandLineRunner ssh = new SshCommandLineRunner(ip, username, password, port);
    ssh.Connect();
    string output1 = ssh.ExecuteCommand("ls");

    ssh.ExecuteCommand("sudo iptables -L -n");
    Thread.Sleep(1000);
    string output2 = ssh.ExecuteCommand(password);

    ssh.ExecuteCommand("sudo iptables -L -n \n");
    Thread.Sleep(1000);
    string output3 = ssh.ExecuteCommand(password);
}

当此函数运行时,我可以成功连接到远程pc,output1具有正确的值,但output2和output3为空。实际上很明显,在sudo命令之后需要输入密码。 我已经阅读了关于ssh .net的大部分问题。一些类似的问题仍未得到答复。

SSH .NET : freeze upon sudo su - user2 (他或她不知道密码,但我知道我不知道如何通过代码输入密码)

How to su with SSH.Net? (我使用了创建shell方法,但是我无法理解这是什么,并且像这个问题我得到了“上次登录:......”输出。)

2 个答案:

答案 0 :(得分:3)

最安全的方法,就像注释中提到的那样,是使用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访问权限的其他用户显示您的密码。如果您是唯一的用户,或者如果您不在乎其他人都能看到您的密码,那么这对您来说可能更方便。

示例:

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);
}

最后,还可以让脚本将密码打印到stdin。这样,您的密码将不会与命令行的其余部分一起记录;但是这仍然没有那么安全,因为任何具有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'

答案 1 :(得分:1)

您可以对Renci库使用相同的bash命令,并将其安装在服务器的“ sshpass”包中。在这种情况下,您可以使用:

SshClient client = new SsClient(IP_server, username, password);
client.Connect();
var commandToSend = client.CreateCommand("sshpass -p \"password\" sudo iptables -L");
commandToSend.Execute();
string response = commandToSend:Result.ToString();
Console.WriteLine("Response: " + response);