SSH.NET 在 C# 中连接到 AWS Managed SFTP 服务器时超时
SSH.NET timeout when connecting to AWS Managed SFTP server in C#
我在尝试建立与 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 时,我没有收到任何响应。
谢谢,吉姆
根据RFC 4253 Section 4.2. Protocol Version Exchange:
When the connection has been established, both sides MUST send an identification string.
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像上面的那样。
我在尝试建立与 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 时,我没有收到任何响应。
谢谢,吉姆
根据RFC 4253 Section 4.2. Protocol Version Exchange:
When the connection has been established, both sides MUST send an identification string.
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像上面的那样。