JSch项目中的SSH_MSG_DISCONNECT异常分析与解决方案
jsch fork of the popular jsch library 项目地址: https://gitcode.com/gh_mirrors/jsc/jsch
问题背景
在使用JSch库(从com.jcraft迁移到com.github.mwiede版本)连接特定SFTP服务器时,开发人员遇到了一个连接异常。在TLS协商完成后,系统抛出JSchSessionDisconnectException: SSH_MSG_DISCONNECT: 2 Failed to read binary packet data!
错误。该问题出现在Java 17环境下,使用JSch 0.2.21版本。
技术分析
通过对服务器配置的分析,我们发现该SFTP服务器支持多种加密算法和协议,包括:
- 密钥交换算法:curve25519-sha256、diffie-hellman-group-exchange-sha256等16种
- 服务器主机密钥算法:ssh-rsa、rsa-sha2-512、rsa-sha2-256
- 加密算法:aes256-gcm、chacha20-poly1305等15种
- MAC算法:hmac-sha2-512、hmac-sha2-256等15种
尽管客户端已正确配置了服务器主机密钥算法(包括rsa-sha2-512、rsa-sha2-256和ssh-rsa),并且在TLS协商阶段日志显示一切正常,但连接仍然在认证阶段失败。
根本原因
深入分析后发现,问题源于服务器软件(疑似SecureFX)对SSH扩展信息(ext-info)消息的处理存在缺陷。JSch在认证过程中会发送SSH_MSG_EXT_INFO消息,而某些服务器实现无法正确处理这些扩展信息,导致连接中断。
解决方案
针对这一问题,我们有两种可行的解决方案:
-
完全禁用服务器签名算法扩展: 通过设置
session.setConfig("enable_server_sig_algs", "no")
,可以完全禁用与服务器签名算法相关的扩展信息交换。 -
推荐方案:仅禁用认证阶段的扩展信息: 更优的解决方案是使用
session.setConfig("enable_ext_info_in_auth", "no")
,这样:- 仍然允许服务器发送扩展信息(如server-sig-algs)
- 仅阻止客户端在认证阶段发送ext-info扩展消息
- 保持了最大程度的兼容性
实施建议
对于遇到类似问题的开发者,建议按照以下步骤操作:
-
在创建Session对象后,添加配置:
session.setConfig("enable_ext_info_in_auth", "no");
-
保持其他安全配置不变,包括:
session.setConfig("server_host_key", "rsa-sha2-512,rsa-sha2-256,ssh-rsa"); session.setConfig("PubkeyAcceptedAlgorithms", "rsa-sha2-512,rsa-sha2-256,ssh-rsa");
-
进行充分的测试,确保文件传输等后续操作正常。
总结
这一案例展示了在SSH/SFTP客户端开发中,不同服务器实现可能存在细微的协议处理差异。JSch库提供了灵活的配置选项来应对这些兼容性问题。通过合理配置扩展信息交换行为,可以在保持安全性的同时提高与各种SFTP服务器的兼容性。
对于企业级应用开发,建议在支持多种SFTP服务器的场景下,将enable_ext_info_in_auth
设置为可配置参数,以便根据实际服务器环境灵活调整。
jsch fork of the popular jsch library 项目地址: https://gitcode.com/gh_mirrors/jsc/jsch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考