在 C# 中连接到 AWS 托管 SFTP 服务器时 SSH.NET 超时

Jim*_*Jim 3 c# ssh sftp amazon-web-services ssh.net

我在尝试建立与 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
}
Run Code Online (Sandbox Code Playgroud)

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

有谁知道我在这里可能会错过什么?

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

从 C# 代码中进行 Wireshark 捕获

从 sFTP 实用程序中捕获 Wireshark

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

谢谢,吉姆

Mar*_*ryl 5

这在旧版本的 SSH.NET 和 Amazon Managed SFTP 服务器端都存在错误。


根据RFC 4253 第 4.2 节。协议版本交换

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

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)));
Run Code Online (Sandbox Code Playgroud)

...在此块上方:

Match versionMatch;

//  Get server version from the server,
//  ignore text lines which are sent before if any
while (true)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

...应该解决问题。

另请考虑向亚马逊报告该错误。

已向 SSH.NET 报告了该错误, 包括所需的更改。该修复包含在 SSH.NET 2020.0.0 及以上版本中。


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

例如,我的WinSCP .NET 程序集与 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
}
Run Code Online (Sandbox Code Playgroud)

WinSCP GUI 可以为您生成类似上面的代码模板。