記錄JSch連線SFTP Exception:Algorithm negotiation fail問題解決

zcy99發表於2024-08-12

問題描述:關於正式環境訪問外網連線不成功


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包,重新啟動服務,測試是否可以訪問。

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中進行配置

相關文章