You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WCF服务使用SSH.NET连接OpenSSH SFTP失败问题排查

WCF调试时SSH.NET连接本机OpenSSH失败排查指南

问题背景

  • 生产环境基于.NET 4.5.2搭建集成服务层,运行多个WCF服务,其中一个服务通过SFTP连接同机部署的SFTP服务器,采用用户名密码认证完成文件读取、移动操作,生产环境运行稳定无异常。
  • 本地调试环境为Windows Server 2012 R2,已安装OpenSSH(版本为OpenSSH_for_Windows_8.9p1, LibreSSL 3.4.3),使用Visual Studio 2019(16.8.6)以管理员身份启动调试。项目依赖Renci SSH.NET v2016.0.0版本,受条件限制无法升级该依赖,仅需在开发环境完成调试即可。
  • 异常现象:在CMD、FileZilla中使用指定用户名密码均可正常连接SFTP;独立编写的简易控制台应用也可正常连接、读取目标目录文件。但调试简易WCF服务及服务宿主时连接均失败,抛出错误:An existing connection was forcibly closed by the remote host。

复现代码与错误信息

正常运行的控制台连接代码

SftpClient _client = new SftpClient(host, u1, password1);
_client.Connect();

WCF服务中的连接代码

public string GetSFTPConnection(ConnectionDetails connectionDetails)
{
    try
    {
        SftpClient _client = new SftpClient(connectionDetails.Host, connectionDetails.UserName, connectionDetails.Password);
        _client.Connect();

        if (_client.IsConnected)
        {
            return "SFTP Connected Successfully!";
        }

        return "SFTP Connection Failed!";
    }
    catch (Exception e)
    {
        return $"SFT Connection Error@ {e}";
    }
}

不同地址连接的错误差异

  • 使用localhost连接:返回错误An existing connection was forcibly closed by the remote host
  • 使用127.0.0.1连接:返回错误Server response does not contain SSH protocol identification.
  • 使用环境IP(10.xx.xx.xx)连接:返回错误Permission denied (password).
  • 使用计算机名连接:返回错误An existing connection was forcibly closed by the remote host

完整错误栈

InnerException = An existing connection was forcibly closed by the remote host
StackTrace = at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout)
             at Renci.SshNet.Session.Connect()
             at Renci.SshNet.BaseClient.Connect()
             at SFTPServiceNew.Service1.GetSFTPConnection(ConnectionDetails connectionDetails) in C...
   
   
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
 <s:Header />
  <s:Body>
    <GetSFTPConnectionResponse xmlns="http://tempuri.org/">
      <GetSFTPConnectionResult>SFT Connection Error@ Renci.SshNet.Common.SshConnectionException: An existing connection was forcibly closed by the remote host ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at Renci.SshNet.Abstractions.SocketAbstraction.Read(Socket socket, Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
   at Renci.SshNet.Session.SocketRead(Int32 length, Byte[] buffer)
   at Renci.SshNet.Session.ReceiveMessage()
   at Renci.SshNet.Session.MessageListener()
   --- End of inner exception stack trace ---
   at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout)
   at Renci.SshNet.Session.Connect()
   at Renci.SshNet.BaseClient.Connect()
   at SFTPServiceNew.Service1.GetSFTPConnection(ConnectionDetails connectionDetails) in C:...</GetSFTPConnectionResult>
    </GetSFTPConnectionResponse>
  </s:Body>
</s:Envelope>

排查步骤

之前尝试执行的mkpasswd -l -u [my_user_account] >> etc\passwd是Linux平台OpenSSH的配置逻辑,Windows版OpenSSH 8.9默认直接对接Windows系统账户体系,不会读取安装目录下的etc\passwd文件,这个方向不需要再尝试。按以下顺序排查即可:

  1. 确认WCF宿主的实际运行身份
    控制台应用能正常连接,核心差异是进程运行上下文,不要默认管理员启动VS就等于WCF服务以你的账户运行:
    • 如果使用IIS Express作为WCF宿主,默认会以当前登录用户的受限令牌运行,部分场景不会继承管理员权限,甚至会使用应用池配置的虚拟账户运行
    • 如果是自托管宿主(控制台/Windows Service做宿主),打开任务管理器找到对应WCF宿主进程,查看详细信息栏的用户名,确认和能正常连接SFTP的控制台进程的运行用户名完全一致
    • 快速验证:在WCF连接SFTP的代码里临时加一行返回WindowsIdentity.GetCurrent().Name,调用接口直接获取当前进程运行的用户名,和测试用控制台返回的用户名对比,不一致的话先把WCF宿主的运行身份改成和正常连接的控制台完全一致。
  2. 解决127.0.0.1连接的协议识别错误
    这个错误说明你访问的22端口根本不是OpenSSH服务在响应,大概率是端口被占用,或者WCF进程的流量被代理/安全软件转发:
    • 执行命令netstat -ano | findstr ":22",确认22端口的监听进程是sshd.exe,如果是其他进程占用,要么更换OpenSSH的监听端口,要么关闭占用22端口的其他服务
    • 检查系统代理、安全软件配置:打开控制面板-Internet选项-连接-局域网设置,确认是否开启了全局代理,临时关闭代理工具、安全软件后再测试,SSH.NET 2016版本本身不会读取系统代理,但部分安全软件的LSP驱动会强制转发本地回环流量。
  3. 解决10网段IP连接的密码拒绝错误
    这个错误说明TCP连接已经正常建立,但是OpenSSH拒绝了密码认证:
    • Windows版OpenSSH默认对非回环地址的连接,会校验账户的网络访问权限:打开本地安全策略-本地策略-用户权限分配,确认你使用的SFTP账户在“允许从网络访问这台计算机”列表中,同时不在“拒绝从网络访问这台计算机”列表内
    • 打开OpenSSH配置文件C:\ProgramData\ssh\sshd_config,确认PasswordAuthentication yes配置项没有被注释,也没有配置AllowUsers/DenyUsers规则拦截你的账户,修改配置后重启sshd服务再测试。
  4. 解决localhost/计算机名连接被强制断开的问题
    这个问题是老版本SSH.NET和新版OpenSSH的加密算法不兼容导致的:OpenSSH 8.9默认禁用了一批老旧不安全的密钥交换、加密算法,而2016版SSH.NET默认只支持这些老算法,握手阶段会被sshd直接断开连接。控制台能正常连接是因为普通控制台进程的加密策略限制更宽松,而WCF服务运行在服务宿主上下文下,系统会施加更严格的加密套件限制。
    临时调整sshd配置兼容老版本SSH.NET即可(仅用于本地调试,不要带到生产环境):在sshd_config末尾添加以下两行配置:
    KexAlgorithms +diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
    Ciphers +aes128-cbc,aes256-cbc,3des-cbc
    
    保存后重启sshd服务,再测试连接即可。另外可以检查C:\Windows\System32\drivers\etc\hosts文件,确认localhost没有被解析到非回环地址,计算机名对应的IP为本机正确IP。

内容的提问来源于stack exchange,提问作者MichaelO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 03:06:42