【问题标题】:C# multi-hop SSH (SSH through SSH)C# 多跳 SSH(通过 SSH 进行 SSH)
【发布时间】:2021-12-05 13:38:31
【问题描述】:

我编写了一个 C# 控制台程序,通过 SSH 从 A(Windows 10,控制台 C# 应用程序)连接到 B(Linux 服务器)并从那里连接到 C(Linux 服务器),但我无法从 B 连接到 C(从A到B没问题)。 当我通过 Windows 终端从 A 连接到 B 并从 B 的终端连接到 C 时,它可以正常工作,因此我证明我的凭据很好。

  • 我在 C# 中使用 Renci.SshNet

  • 我使用.Connect()、.Disconnect() 和.Execute() 扩展方法创建了一个类Server,然后创建了两个类实例Broker 和Destination

  • 我的代码如下:

     if (Broker.Connect())
     {
       Broker.Execute("pwd");
    
       if (Destination.Connect())
       {
          Destination.Execute("pwd");
          Destination.Disconnect();
       }
       Broker.Disconnect();
     }
    
  • Ssh 连接对象的创建类似于var broker = new SftpClient("Ip", Port, "User", "Pass")

  • 然后我在内部使用broker.Connect() 和broker.Disconnect() in Renci.Ssh.Net lib 给定方法

  • 致broker.Execute("cmd")我基本上是这样做的

    var output = host.Ssh.RunCommand(str);
    var res0 = output.ExitStatus;
    var res1 = output.Result;
    var res2 = output.Error;
    
  • 我的代码适用于第一部分,因为我设法获得了Broker.Execute("pwd") 的输出,但它没有连接到Destination.Connect(),返回消息A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond

  • 我的目标是使用 C# 中的自动化进程进行多跳:用户不得与任何控制台交互,并且我不能在 Linux 上修改或存储任何文件网站

知道问题出在哪里吗?

提前致谢,

【问题讨论】:

  • 这很模糊。请edit您的问题包含您程序中的相关代码,并准确描述运行它时发生的情况。包括您收到的任何错误消息和堆栈跟踪。
  • 请在您的主机上尝试ssh userc@hostc -J userB@hostb。如果可行,您可以将主机添加到您的 .ssh/config 文件中
  • Destination.Connect 可能会尝试直接从 hostA 连接到 HostC,我不相信它会为此使用 host-B
  • @jeb 使用ssh userc@hostc -J userB@hostb ...我在哪里提供密码?对于Destination.Connect 是的,这也是我的猜测……但我不知道/不知道如何解决它……
  • 在命令行中使用ssh,它会要求输入密码。然后避免密码使用密钥

标签: c# linux ssh ssh-tunnel


【解决方案1】:

我想在这里总结一下我是如何在网上和@jeb 收集的一些有价值的提示的帮助下解决这个问题的:

打开一个cmd.exe控制台,输入ssh userC@hostC -p portC-J userB@hostB - p portB(portB和portC如果是默认端口22可以省略)然后会提示输入passwordB和passwordC - in这个命令。 如果连接成功,您将在 hostC 控制台上,并且将设法做任何您想做的事情。

您需要的代码是:

static void RunSshHop(params string[] cmds)
{
    try
    {
        using (Process p = new Process())
        {
            p.StartInfo = new ProcessStartInfo("cmd.exe")
            {
                RedirectStandardInput = true,
                UseShellExecute = false,
                //WorkingDirectory = @"d:\" // dir of your "cmd.exe"
            };

            p.OutputDataReceived += p_DataReceived;
            p.ErrorDataReceived += p_DataReceived;

            p.Start();

            // way 1: works
            foreach (var e in cmds)
                p.StandardInput.Write($"{e}\n"); // cannot use 'WriteLine' because Windows is '\r' and Linux is '\n'

            /* way 2: works as well
            using (var sw = p.StandardInput)
            {
                foreach (var e in cmds)
                    if (sw.BaseStream.CanWrite)
                        sw.Write($"{e}\n"); // cannot use 'WriteLine' because Windows is '\r' and Linux is '\n'
            }
            //*/

            p.WaitForExit();

            if (p.HasExited)
            {
                Console.WriteLine($"ExitCode: {p.ExitCode}");
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

你可以这样称呼它:

static void Main(string[] args)
{
    RunSshHop(
       "ssh userC@hostC -p portC-J userB@hostB - p portB",
       "pwd",
       //"...",
       "ls"
    );
}

为避免输入每个主机的密码,您还可以像这样创建一个 SSH 密钥对:

  • 打开cmd.exe控制台
  • 输入ssh-keygen -t rsa
  • 选择保存要生成的公钥和私钥的路径(按enter使用默认目的地)
  • 复制目的地,稍后您将需要它来取回您的密钥 :-)
  • 要管理自动化流程,您必须将passphrase 留空 - 生成密钥后,通过 ssh 登录到第一台主机,例如 ssh youruser@firsthost -p hostport(如果端口是默认的 22,则可以忽略 -p hostport 部分)
  • 输入ssh-copy-id youruser@firsthost -p hostport
  • 接受
  • 对第二台主机重复该过程

【讨论】:

    猜你喜欢
    • 2018-07-23
    • 2021-10-28
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-26
    • 1970-01-01
    相关资源
    最近更新 更多