问题描述:关于正式环境访问外网连接不成功
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 serversession = jsch.getSession(user, host, port);session.setPassword(password);session.setConfig("StrictHostKeyChecking", "no");session.connect();// Open an SFTP channelChannel channel = session.openChannel("sftp");channel.connect();channelSftp = (ChannelSftp) channel;// Download the filetry (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,安装别的版本
JDK版本1.7以下,对应支持的算法较少,需要单独在JDK中进行配置
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 的系统。