前言

最近做项目,升级了服务器的操作系统版本,openSSH被系统默认升级了,发现sftp客户端(Java)连接出现了失败,报错Algorithm negotiation fail,然后发现一系列的安全漏洞和官方版本在2018年后就不维护了,虽然0.1.55和0.1.54还能继续用,但是加密和加签算法不再迭代的隐患考虑,切换社区维护版是最终的解决办法。

准备demo

检查笔者以前的专门小主机的openssh版本:OpenSSH_8.9p1

并不是最新版,不过也可以复现问题,实际上openSSH8.2p1也可能有问题

随便写个demo

package com.feng.jsch.demo;

import com.jcraft.jsch.*;

import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Properties;

public class JschDemo {
    public static void main(String[] args) {
        String host = "192.168.0.105";
        int port = 22;
        String username = "tom";
        String password = "xxxxxx";
        String localFile = "/Users/huahua/Fleet-1.48.261.dmg";
        String remoteFile = "/home/sftp_users/tom/Fleet-1.48.261.dmg";

        JSch jsch = new JSch();
        Session session = null;

        try {
            // 创建 Session 并设置属性
            session = jsch.getSession(username, host, port);
            session.setPassword(password);

            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);

            // 建立连接
            session.connect();

            // 打开 SFTP 通道
            Channel channel = session.openChannel("sftp");
            channel.connect();
            ChannelSftp sftpChannel = (ChannelSftp) channel;

            // 上传文件
            sftpChannel.put(Files.newInputStream(Paths.get(localFile)), remoteFile, ChannelSftp.OVERWRITE);
            System.out.println("文件上传成功!");

            sftpChannel.ls("/home/sftp_users/tom/").forEach(System.out::println);
            sftpChannel.rm("/home/sftp_users/tom/Fleet-1.48.261.dmg");
            sftpChannel.ls("/home/sftp_users/tom").forEach(System.out::println);


            // 关闭连接
            sftpChannel.exit();
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

0.1.50

在依赖0.1.50版本时

<dependencies>
    <dependency>
        <groupId>com.jcraft</groupId>
        <artifactId>jsch</artifactId>
        <version>0.1.50</version>
    </dependency>
</dependencies>

提示有安全漏洞,忽略直接连吧

com.jcraft.jsch.JSchException: Algorithm negotiation fail
	at com.jcraft.jsch.Session.receive_kexinit(Session.java:582)
	at com.jcraft.jsch.Session.connect(Session.java:320)
	at com.jcraft.jsch.Session.connect(Session.java:183)
	at com.feng.jsch.demo.JschDemo.main(JschDemo.java:32)

就报错了,按照提示升级0.1.54

然后升级0.1.54吧,最新版本是0.1.55

实测上传成功

看看其中有什么变更吧,实际上现在能使用的就这2个版本了

官方网站已经打不开了,且Maven仓库说项目移交到开源社区维护了,最后的官方版本是2018年发布的

通过Maven信息,可以看到是jdk1.6打包的

笔者这里测试成功,但是OpenSSH因为安全漏洞问题会移除一些加密加签算法,而jsch不再更新。所以切换为社区版是唯一的解决办法,同理虽然官方版本还可以使用,但是每台服务器的openSSH版本和加密加签算法不可能完全一样,所以不一定适合其他操作系统和其他openSSH版本。有可能使用官方最新版本还是会出现算法缺少的报错。

看到网上说在ssh中加入已经移除的加密加签算法,但是这个安全性可能需要评估,毕竟ssh默认移除这些算法也是有理由的。

为了验证兼容情况,笔者升级OpenSSH版本为

实测官方版本0.1.55仍然可以访问,当然笔者测试有限,不排除出现不兼容的情况。

社区版

根据Maven提示,使用0.2.17(这个版本Maven使用最高),实际推荐是0.2.15或以上版本,以下版本有安全漏洞

        <dependency>
            <groupId>com.github.mwiede</groupId>
            <artifactId>jsch</artifactId>
            <version>0.2.17</version>
        </dependency>

代码什么都不改即可,兼容性真好,因为加入了新算法,所以ssh连接时,速度会快一点,测试效果与官方版本一致

总结

目前ssh主要用于登录远程Linux服务器,同时文件可以在这个基础上传输,所以有sftp也是使用的ssh通道,后面发展出各种骚操作,比如通过ssh登录数据库,其实ssh就是提供通道,用于传输文件,数据库连接管理。ssh发展了很多代,在openSSH7的时候基本上都是兼容很多旧的算法,但是在openSSH8开始,移除了很多老的算法,所以如果客户端没更新算法库,很可能出现算法匹配不上的报错Algorithm negotiation fail。类似https,加密和加签算法是客户端和服务端协商,看看大家都认可那些算法,从共有的算法选出一个,所以国密ssl的网页,在chrome浏览器是访问不了的,因为客户端不支持国密ssl加密套件。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐