记录JSch连接SFTP Exception:Algorithm negotiation fail问题解决
问题描述:关于正式环境访问外网连接不成功
1、首先检查是否开放防火墙(已确认开放),策略开放后,通过命令连接是否畅通:

通过telnet命令,可以得出,访问畅通。
telnet 192.168.1.1 22
2、查看生产环境日志,观察生产环境访问外网服务器异常:
抛出异常,提示:算法协商失败
com.jcraft.jsch.JSchException: Algorithm negotiation fail

3、查找生产代码,本地通过代码模拟连接sftp,还原问题,
通过查看生产环境,jar引入为jsch-0.1.54
代码示例:
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class SFTPDownloadExample {
public static void main(String[] args) {
String host = "192.168.1.1";
int port = 22;
String user = "admin";
String password = "root";
String remoteFile = "/PEP/ac.ZIP";
String localFile = "ac.ZIP";
JSch jsch = new JSch();
Session session = null;
ChannelSftp channelSftp = null;
try {
// Connect to the server
session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
// Open an SFTP channel
Channel channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp) channel;
// Download the file
try (OutputStream outputStream = new FileOutputStream(localFile)) {
channelSftp.get(remoteFile, outputStream);
}
System.out.println("File downloaded successfully!");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (channelSftp != null && channelSftp.isConnected()) {
channelSftp.disconnect();
}
if (session != null && session.isConnected()) {
session.disconnect();
}
}
}
}
使用测试类,执行此示例代码,模拟生产环境请求。

本地重现问题,可以确认访问是没有问题的,可能出现在jar包或ssh版本上。
sftp和ssh使用的是同一加密算法,算法协商失败,意思就是客服端和服务端支持的算法不一致,然后就出现这个提示,因此需要检查一下支持的算法。
4、查看SSH版本
ssh -V

生产环境使用的版本为5.3
可以使用以下命令查看 Linux 服务器 SSH 默认支持的算法:
ssh -Q cipher ssh -Q mac ssh -Q kex ssh -Q key
这些命令会列出支持的加密算法、消息认证码 (MAC) 算法、密钥交换算法和公钥算法。
如果 ssh -Q 命令不可用,你可以查看 SSH 配置文件 /etc/ssh/sshd_config 来了解支持的算法。你也可以使用 ssh -vv 进行调试,这将显示 SSH 客户端在连接时使用的详细信息,包括支持的算法。例如:
ssh -vv user@hostname
在输出中,你会看到有关加密算法、MAC 和密钥交换算法的信息。
默认情况下,SSH通常支持以下几种算法:
1. 加密算法:AES (Advanced Encryption Standard) 和 3DES (Triple Data Encryption Standard)。
2. 散列算法:SHA-2 (如SHA-256、SHA-512)。
3. 密钥交换算法:Diffie-Hellman (DH) 和 Elliptic Curve Diffie-Hellman (ECDH)。
这些算法可以根据具体的SSH实现和版本有所不同。
我们当前使用的 jsch-0.1.54.jar 包,此版本大概为2016年9月3日

在这个版本中,JSCH 支持的默认算法主要包括: 加密算法: 对称加密算法:aes128-cbc, aes192-cbc, aes256-cbc, blowfish-cbc, 3des-cbc 消息认证码 (MAC) 算法: hmac-md5, hmac-sha1 密钥交换算法: diffie-hellman-group1-sha1 公钥算法: ssh-rsa, ssh-dss 这些算法在较新的版本中可能会有所变化或增加新的选项
解决方案:
1、将jsch版本升级到新一点的版本
2、服务器向下兼容低版本算法
3、降低SSH版本,让对应的客户端可以直接连上,卸载当前ssh,安装别的版本
1、将jsch版本升级到新一点的版本
获取新的jar包,替换掉当前版本的jar包,重新启动服务,测试是否可以访问。
更新新的jar包以后,提示:
com.jcraft.jsch.JSchException: java.security.InvalidKeyException: Illegal key size
这里需要安装 JCE 无限强度策略文件
下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
注意备份原有jar包
下载解压后,把jar文件上传到需要安装jce机器上JDK或JRE的security目录下,覆盖源文件即可。
2、服务器向下兼容低版本算法
修改ssh的配置文件
/etc/ssh/sshd_config
在配置文件后新增
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
对应的算法必须包含客户端需要支持的算法,配置完成后重启ssh服务
要重启 SSH 服务,可以使用以下命令,具体命令可能取决于你使用的 Linux 发行版:
对于基于 systemd 的系统(如 Ubuntu 16.04 及以后版本、CentOS 7 及以后版本):
sudo systemctl restart sshd
对于基于 SysVinit 的系统(如较旧的 Debian 版本):
sudo service ssh restart
service sshd restart:通常用于基于 SysVinit 的系统。systemctl restart sshd.service:用于基于 systemd 的系统。
其他问题导致:
JDK版本1.7以下,对应支持的算法较少,需要单独在JDK中进行配置

浙公网安备 33010602011771号