国产服务器引发的痛java.io.IOException: Key exchange was not finished, connection is closed.Cannot negotiate
ssh升级完报错:
java.io.IOException: Key exchange was not finished, connection is closed.Cannot negotiate, proposa
原因
是ssh中的key交换算法不兼容导致
解决方式一
vi /etc/ssh/sshd_config
#最后一行
KexAlgorithms diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group1-sha1,curve25519-sha256@libssh.org
HostKeyAlgorithms ssh-dss,ssh-rsa
#重启ssh服务
service sshd restart
解决方式二
由于甲方不让改服务器配置只能寻求他法,最终只能从代码层面入手。原有的一些密钥算法已经不再支持,我们目前使用的Jcraft公司发布的Jsch版本已经没办法满足,需要进行升级。但是Jcraft公司的Jsch0.1.55版本从2018年开始就停止维护,我们不得不升级到另一个mwiede继续维护的Jsch版本(基于原有0.1.55fork的分支)以满足更多算法的需要。
- 依赖修改后
<dependency>
<groupId>com.github.mwiede</groupId>
<artifactId>jsch</artifactId>
<version>0.2.16</version>
</dependency>
RSA/SHA1 签名算法在新版本Jsch中由于安全原因已经被默认关闭,由于有些上下游仍然使用旧版本的OpenSSH服务,因为没办法新版Jsch没办法连接,从以上报错信息可以看到,对方服务器需要ssh-rsa,ssh-dss,因此我们需要在创建连接前对SFTP Session额外添加以下配置:
session.setConfig("server_host_key", session.getConfig("server_host_key") + ",ssh-rsa");
session.setConfig("PubkeyAcceptedAlgorithms", session.getConfig("PubkeyAcceptedAlgorithms") + ",ssh-rsa,rsa-sha2-256")
- com.jcraft.jsch.JSchProxyException: ProxySOCKS5: stream is closed" - 同上,由于我们代理服务器也是使用的是旧版OpenSSH,因此加入上面配置即可。
- com.jcraft.jsch.JSchException: Session.connect: java.security.InvalidAlgorithmParameterException: DH key size must be multiple of 64, and can only range from 1024 to 2048 (inclusive). The specific key size 3047 is not supported. - 这是由于当前JDK版本不支持更高位数的Diffie-Hellman密钥交换算法的密钥长度,这里我们可以通过以下参数指定推荐的密钥长度
session.setConfig("dhgex_min", "1024")
session.setConfig("dhgex_max", "2048")
session.setConfig("dhgex_preferred", "2048")
完整代码如下
// 设置JSch
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, PORT);
session.setPassword(passwd);
// 设置配置信息
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setConfig("server_host_key", session.getConfig("server_host_key") + ",ssh-rsa,ssh-dss");
session.setConfig("PubkeyAcceptedAlgorithms", session.getConfig("PubkeyAcceptedAlgorithms") + ",ssh-rsa,,ssh-dss,rsa-sha2-256");
session.setConfig("dhgex_min", "1024");
session.setConfig("dhgex_max", "2048");
session.setConfig("dhgex_preferred", "2048");
// 连接到服务器
session.connect();
// 进行后续操作
System.out.println("连接成功");
// 断开连接
session.disconnect();