|
|
|
package com.zhonglai.luhui.ssh.proxy;
|
|
|
|
|
|
|
|
import com.jcraft.jsch.Channel;
|
|
|
|
import com.jcraft.jsch.JSch;
|
|
|
|
import com.jcraft.jsch.JSchException;
|
|
|
|
import com.jcraft.jsch.Session;
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
|
|
import javax.annotation.PostConstruct;
|
|
|
|
import javax.annotation.PreDestroy;
|
|
|
|
|
|
|
|
@Component
|
|
|
|
public class SSHChunnel {
|
|
|
|
@Autowired
|
|
|
|
private SSHConfig sshConfig;
|
|
|
|
private JSch jsch;
|
|
|
|
private Session session = null;
|
|
|
|
private Channel channel;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 创建SSH隧道
|
|
|
|
*/
|
|
|
|
public void createChunnel()
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
jsch = new JSch();
|
|
|
|
|
|
|
|
session = jsch.getSession(sshConfig.getUser(),sshConfig.getHost() ,sshConfig.getPort() );
|
|
|
|
session.setPassword(sshConfig.getPassword());
|
|
|
|
// 设置不进行主机密钥检查
|
|
|
|
java.util.Properties config = new java.util.Properties();
|
|
|
|
config.put("StrictHostKeyChecking", "no");
|
|
|
|
session.setConfig(config);
|
|
|
|
|
|
|
|
// 建立SSH连接
|
|
|
|
session.connect();
|
|
|
|
|
|
|
|
} catch (JSchException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void closeChunnel()
|
|
|
|
{
|
|
|
|
if (channel != null) {
|
|
|
|
channel.disconnect();
|
|
|
|
}
|
|
|
|
if (session != null) {
|
|
|
|
session.disconnect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 建立端口转发服务
|
|
|
|
*/
|
|
|
|
public void startChunnel() throws JSchException {
|
|
|
|
// 设置端口转发
|
|
|
|
if (sshConfig.getPortForwardingList() != null) {
|
|
|
|
for (PortForwarding portForwarding : sshConfig.getPortForwardingList()) {
|
|
|
|
int assignedLocalPort = session.setPortForwardingL(portForwarding.getLocalPort(), portForwarding.getRemoteHost(), portForwarding.getRemotePort());
|
|
|
|
System.out.println("Local port " + assignedLocalPort + " is now forwarding to " + portForwarding.getRemoteHost() + ":" + portForwarding.getRemotePort());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 保持连接打开
|
|
|
|
channel = session.openChannel("shell");
|
|
|
|
channel.connect();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 在Bean初始化完成后启动SSH隧道
|
|
|
|
*/
|
|
|
|
@PostConstruct
|
|
|
|
public void init() {
|
|
|
|
if(sshConfig.isEnabled())
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
createChunnel();
|
|
|
|
startChunnel();
|
|
|
|
} catch (JSchException e) {
|
|
|
|
throw new RuntimeException("Failed to start SSH tunnel", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 定期检查SSH连接状态并重连
|
|
|
|
*/
|
|
|
|
@Scheduled(fixedRate = 10000) // 每10秒检查一次
|
|
|
|
public void checkAndReconnect() {
|
|
|
|
if (sshConfig.isEnabled())
|
|
|
|
{
|
|
|
|
if (session == null || !session.isConnected()) {
|
|
|
|
System.out.println("SSH tunnel is disconnected, attempting to reconnect...");
|
|
|
|
try {
|
|
|
|
closeChunnel(); // 先关闭旧的连接
|
|
|
|
createChunnel();
|
|
|
|
startChunnel();
|
|
|
|
System.out.println("SSH tunnel reconnected successfully.");
|
|
|
|
} catch (JSchException e) {
|
|
|
|
System.err.println("Failed to reconnect SSH tunnel: " + e.getMessage());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 在Bean销毁前关闭SSH隧道并取消定时任务
|
|
|
|
*/
|
|
|
|
@PreDestroy
|
|
|
|
public void destroy() {
|
|
|
|
if (session != null && session.isConnected()) {
|
|
|
|
closeChunnel();
|
|
|
|
System.out.println("SSH tunnel closed on application shutdown.");
|
|
|
|
}
|
|
|
|
sshConfig.setIsEnabled(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
} |
...
|
...
|
|