問題描述:關於正式環境訪問外網連線不成功
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中進行配置