JSch如何建立安全的ssh连接
背景介绍
JSch提供了三种ssh连接指纹校验的方式:
“no” : 不校验对端指纹
“yes” : 使用指定的指纹进行校验
“ask” : 采用询问的方式,确认后指纹将存入指定的指纹文件中,后续将使用该指纹进行校验,校验失败则连接失败
可参考官网:https://gitee.com/hyee/jsch
安全分析
如果采用no的方式连接,存在对端仿冒ip进行连接,进而对服务器进行攻击的风险,因此采用ask或yes进行连接安全性更高
解决方案
网上关于采用yes连接的代码非常的少,这里做下详细的介绍:
1、设置为yes,必须指定指纹,JSch提供了setKnownHosts来指定指纹
2、setKnownhosts有两种输入方式:
2.1创建了一个文件(自命名,后文用hostkeyfile代替)存放指纹,将查询到的指纹存入hostkeyfile中,当进行jsch连接时,JSch会读取文件hostkeyfile中的指纹进行匹配,若匹配成功则连接成功,若匹配失败则连接失败
2.2将查询到的指纹搞成输入流,setKnownHosts时作为参数传入,jsch将读取该指纹输入流,进行指纹匹配,若匹配成功则连接成功,若匹配失败则连接失败
3、依据步骤1、2中的技术背景,我们来分析下
若修改为yes,必然要考虑指纹从哪儿来的问题:
一种可以前后台交互的方式,让用户从前台输入;
另一种若无法与用户交互纯后台就只能采用先用no的方式连接一次,存储该指纹后后续使用yes连接了
以上两种解决方案,个人更倾向于第一种,前后台交互,但若由于业务背景的限制这样搞意义不大或者安全性要求没有那么高也可以采用第二种。
4、上代码:
public class JSchTest {
public static void main(String args[]) {
try {
connectChanel();
System.out.println("connect success.");
} catch (JSchException e) {
System.out.println("connect failed.");
}
}
private static void connectChanel() throws JSchException {
String hostip = "*.*.*.*";
String username = "***";
String passwd = "***";
int port = 22;
JSch jsch = new JSch();
jsch.setKnownhosts("D:/hostskeyfile");
Session session = jsch.getSession(username, hostip, port);
session.setPassword(passwd);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "yes");
session.setConfig(config);
session.setTimeout(6000);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
}
}
注意:
1、若D:/hostskeyfile文件未创建将抛异常:
com.jcraft.jsch.JSchException: reject HostKey: ...
at com.jcraft.jsch.Session.checkHost(Session.java:789)
at com.jcraft.jsch.Session.connect(Session.java:345)
at com.jcraft.jsch.Session.connect(Session.java:183)
at JschTest.getChannelWithCheckType(JschTest.java:48)
at JschTest.main(JschTest.java:13)
2、若想获取指纹信息,先采用no的方式连接,jsch将把指纹信息存入指定的已创建的指纹文件中
3、流方式传入指纹在此不上代码了,很简单大家可以自己研究下