【问题标题】:SSH.NET timeout when connecting to AWS Managed SFTP server in C#在 C# 中连接到 AWS Managed SFTP 服务器时 SSH.NET 超时
【发布时间】:2021-05-26 13:24:39
【问题描述】:

我在尝试建立与 AWS 托管 SFTP 服务器的连接时遇到问题。使用我手头的凭据,我可以使用sftp 命令从我的Windows 命令行连接到服务器。这是我的 .NET 代码:

using (var client = new SshClient(new ConnectionInfo(baseHost, user,
            new AuthenticationMethod[]{
                new PrivateKeyAuthenticationMethod(user,new PrivateKeyFile[]{
                    new PrivateKeyFile(keyLocation, pkpassword)
                }),
            }
        )))
{
    client.Connect(); // Timeout here
}

上面的代码到达 client.Connect() 行,然后在 30 秒后超时并出现 Renci.SshNet.Common.SshOperationTimeoutException 异常。当我查看 Wireshark 发生的情况时,我看到sftp 命令行实用程序使用的协议是 SSH,而 SSH.NET 使用的是 TCP,并且数据包大小完全不同。

有人知道我在这里可能缺少什么吗?

我在与上述代码相同的计算机上运行sftp 命令行实用程序。下面的第一个 Wireshark 图像来自上面的 C# 代码。第二个来自 sFTP 实用程序:

当我尝试在原始模式下使用 PuTTY 连接到服务器的端口 22 时,我没有收到任何响应。

谢谢,吉姆

【问题讨论】:

    标签: c# amazon-web-services ssh sftp ssh.net


    【解决方案1】:

    根据RFC 4253 Section 4.2. Protocol Version Exchange

    连接建立后,双方必须发送一个标识字符串。

    SSH.NET 客户端和 Amazon Managed SFTP 服务器均不符合此要求。两者都先等待对方发送标识字符串,然后再发送自己的标识字符串。死锁是不可避免的(仅由超时中断)。这也解释了为什么 Wireshark 不将会话识别为 SSH,因为根本没有交换数据。因此,无法识别协议。

    如果可以修改SSH.NET源代码,将这一行移入Session.Connect

    SocketAbstraction.Send(_socket, Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}\x0D\x0A", ClientVersion)));
    

    ...在此块上方:

    Match versionMatch;
    
    //  Get server version from the server,
    //  ignore text lines which are sent before if any
    while (true)
    {
        ...
    }
    

    ...应该可以解决问题。

    还可以考虑将错误报告给亚马逊。

    我有reported the bug to SSH.NET 包括needed change。该修复程序包含在 SSH.NET 2020.0.0 以上版本中。


    如果您无法更改 SSH.NET 代码,则需要使用另一个 SFTP 库。

    例如,我的 WinSCP .NET assembly 与 Amazon Managed SFTP 服务器兼容。

    这相当于您的代码:

    // Set up session options
    SessionOptions sessionOptions = new SessionOptions
    {
        Protocol = Protocol.Sftp,
        HostName = baseHost,
        UserName = user,
        SshHostKeyFingerprint = ...,
        SshPrivateKeyPath = keyLocation,
        PrivateKeyPassphrase = pkpassword,
    };
    
    using (Session session = new Session())
    {
        // Connect
        session.Open(sessionOptions);
    
        // Your code
    }
    

    WinSCP GUI 可以generate a code template 为您喜欢上面的那个。

    【讨论】:

    • 谢谢马丁!我从 Github 克隆了源代码,并按照 Martin 的建议移动了代码。然后我就可以连接到 AWS sFTP 服务器了。
    猜你喜欢
    • 2022-06-14
    • 2017-02-26
    • 1970-01-01
    • 2020-06-06
    • 2021-07-26
    • 2018-11-03
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多