Files
ssh-manager/backend/src/main/java/com/sshmanager/service/SshService.java

100 lines
3.6 KiB
Java

package com.sshmanager.service;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.sshmanager.entity.Connection;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
@Service
public class SshService {
public SshSession createShellSession(Connection conn, String password, String privateKey, String passphrase)
throws Exception {
JSch jsch = new JSch();
if (conn.getAuthType() == Connection.AuthType.PRIVATE_KEY && privateKey != null && !privateKey.isEmpty()) {
byte[] keyBytes = privateKey.getBytes(StandardCharsets.UTF_8);
byte[] passphraseBytes = (passphrase != null && !passphrase.isEmpty())
? passphrase.getBytes(StandardCharsets.UTF_8) : null;
jsch.addIdentity("key", keyBytes, null, passphraseBytes);
}
Session session = jsch.getSession(conn.getUsername(), conn.getHost(), conn.getPort());
session.setConfig("StrictHostKeyChecking", "no");
// Use only DH-based kex to avoid "Algorithm ECDH not available" on Java 8 / minimal JRE
session.setConfig("kex", "diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1");
if (conn.getAuthType() == Connection.AuthType.PASSWORD && password != null) {
session.setPassword(password);
}
session.connect(10000);
ChannelShell channel = (ChannelShell) session.openChannel("shell");
channel.setPtyType("xterm");
channel.connect(5000);
PipedInputStream pipedIn = new PipedInputStream();
PipedOutputStream pipeToChannel = new PipedOutputStream(pipedIn);
OutputStream channelIn = channel.getOutputStream();
InputStream channelOut = channel.getInputStream();
new Thread(() -> {
try {
byte[] buf = new byte[1024];
int n;
while ((n = pipedIn.read(buf)) > 0) {
channelIn.write(buf, 0, n);
channelIn.flush();
}
} catch (Exception e) {
// Channel closed
}
}).start();
return new SshSession(session, channel, channelOut, pipeToChannel);
}
public static class SshSession {
private final Session session;
private final ChannelShell channel;
private final InputStream outputStream;
private final OutputStream inputStream;
public SshSession(Session session, ChannelShell channel, InputStream outputStream, OutputStream inputStream) {
this.session = session;
this.channel = channel;
this.outputStream = outputStream;
this.inputStream = inputStream;
}
public InputStream getOutputStream() {
return outputStream;
}
public OutputStream getInputStream() {
return inputStream;
}
public void disconnect() {
if (channel != null && channel.isConnected()) {
channel.disconnect();
}
if (session != null && session.isConnected()) {
session.disconnect();
}
}
public boolean isConnected() {
return channel != null && channel.isConnected();
}
}
}