1. 소개
SSH( Secure Shell 또는 Secure Socket Shell이라고도 함)는 한 컴퓨터가 Security되지 않은 네트워크를 통해 다른 컴퓨터에 안전하게 연결할 수 있도록 하는 네트워크 프로토콜입니다 . 이 사용방법(예제)에서는 JSch 및 Apache MINA SSHD 라이브러리를 사용하여 Java로 원격 SSH 서버에 연결 하는 방법을 보여줍니다 .
이 예에서는 먼저 SSH 연결을 연 다음 하나의 명령을 실행하고 출력을 읽고 콘솔에 쓰고 마지막으로 SSH 연결을 닫습니다. 샘플 코드를 가능한 한 간단하게 유지하겠습니다.
2. JSch
JSch 는 SSH 서버에 연결하고 포트 포워딩, X11 포워딩 및 파일 전송을 사용할 수 있게 해주는 SSH2의 Java 구현입니다. 또한 BSD 스타일 라이센스에 따라 라이센스가 부여되며 Java와 SSH 연결을 설정하는 쉬운 방법을 제공합니다.
먼저 pom.xml 파일에 JSch Maven 의존성 을 추가해 보겠습니다 .
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
2.1. 구현
JSch를 사용하여 SSH 연결을 설정하려면 사용자 이름, 비밀번호, 호스트 URL 및 SSH 포트가 필요합니다 . 기본 SSH 포트는 22이지만 SSH 연결에 다른 포트를 사용하도록 서버를 구성할 수 있습니다.
public static void listFolderStructure(String username, String password,
String host, int port, String command) throws Exception {
Session session = null;
ChannelExec channel = null;
try {
session = new JSch().getSession(username, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
channel.setOutputStream(responseStream);
channel.connect();
while (channel.isConnected()) {
Thread.sleep(100);
}
String responseString = new String(responseStream.toByteArray());
System.out.println(responseString);
} finally {
if (session != null) {
session.disconnect();
}
if (channel != null) {
channel.disconnect();
}
}
}
코드에서 볼 수 있듯이 먼저 클라이언트 세션을 만들고 SSH 서버에 연결하도록 구성합니다. 그런 다음 채널 유형을 제공하는 SSH 서버와 통신하는 데 사용되는 클라이언트 채널을 만듭니다. 이 경우 exec로 셸 명령을 서버에 전달할 것입니다.
또한 서버 응답이 기록될 채널의 출력 스트림을 설정해야 합니다. channel.connect() 메서드를 사용하여 연결을 설정한 후 명령이 전달되고 수신된 응답이 콘솔에 기록됩니다.
JSch가 제공하는 다양한 구성 매개변수를 사용하는 방법을 살펴보겠습니다 .
- StrictHostKeyChecking – 알려진 호스트 중에서 호스트 공개 키를 찾을 수 있는지 애플리케이션이 확인할 것인지 여부를 나타냅니다. 또한 사용 가능한 매개변수 값은 ask , yes 및 no 이며, 여기서 ask 는 기본값입니다. 이 속성을 yes 로 설정하면 JSch는 호스트 키를 known_hosts 파일에 자동으로 추가하지 않으며 호스트 키가 변경된 호스트에 대한 연결을 거부합니다. 이렇게 하면 사용자가 모든 새 호스트를 수동으로 추가해야 합니다. no 로 설정하면 JSch는 알려진 호스트 List에 새 호스트 키를 자동으로 추가합니다.
- compression.s2c – 서버에서 클라이언트 응용 프로그램으로의 데이터 스트림에 압축을 사용할지 여부를 지정합니다. 사용 가능한 값은 zlib 이고 두 번째 값이 기본값인 경우 없음입니다 .
- compression.c2s – 클라이언트-서버 방향에서 데이터 스트림에 압축을 사용할지 여부를 지정합니다. 사용 가능한 값은 zlib 이고 두 번째 값이 기본값인 경우 없음입니다 .
메모리 누수를 방지하려면 서버와의 통신이 끝난 후 세션과 SFTP 채널 을 닫는 것이 중요합니다 .
3. 아파치 미나 SSHD
Apache MINA SSHD 는 Java 기반 애플리케이션에 대한 SSH 지원을 제공합니다. 이 라이브러리는 확장 가능한 고성능 비동기 IO 라이브러리인 Apache MINA를 기반으로 합니다.
Apache Mina SSHD Maven 의존성을 추가해 보겠습니다 .
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>2.5.1</version>
</dependency>
3.1. 구현
Apache MINA SSHD를 사용하여 SSH 서버에 연결하는 코드 샘플을 살펴보겠습니다.
public static void listFolderStructure(String username, String password,
String host, int port, long defaultTimeoutSeconds, String command) throws IOException {
SshClient client = SshClient.setUpDefaultClient();
client.start();
try (ClientSession session = client.connect(username, host, port)
.verify(defaultTimeoutSeconds, TimeUnit.SECONDS).getSession()) {
session.addPasswordIdentity(password);
session.auth().verify(defaultTimeoutSeconds, TimeUnit.SECONDS);
try (ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
ClientChannel channel = session.createChannel(Channel.CHANNEL_SHELL)) {
channel.setOut(responseStream);
try {
channel.open().verify(defaultTimeoutSeconds, TimeUnit.SECONDS);
try (OutputStream pipedIn = channel.getInvertedIn()) {
pipedIn.write(command.getBytes());
pipedIn.flush();
}
channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED),
TimeUnit.SECONDS.toMillis(defaultTimeoutSeconds));
String responseString = new String(responseStream.toByteArray());
System.out.println(responseString);
} finally {
channel.close(false);
}
}
} finally {
client.stop();
}
}
Apache MINA SSHD로 작업할 때 JSch와 매우 유사한 이벤트 시퀀스가 있습니다. 먼저 SshClient 클래스 인스턴스를 사용하여 SSH 서버에 대한 연결을 설정 합니다. SshClient.setupDefaultClient()로 초기화하면 대부분의 사용 사례에 적합한 기본 구성이 있는 인스턴스로 작업할 수 있습니다. 여기에는 암호, 압축, MAC, 키 교환 및 서명이 포함됩니다.
그런 다음 ClientChannel을 만들고 여기 에 ByteArrayOutputStream 을 연결하여 응답 스트림으로 사용할 것입니다. 보시다시피 SSHD에는 모든 작업에 대해 정의된 시간 제한이 필요합니다. 또한 Channel.waitFor() 메서드를 사용하여 명령이 전달된 후 서버 응답을 기다리는 시간을 정의할 수 있습니다 .
SSHD가 완전한 콘솔 출력을 응답 스트림에 기록 한다는 점에 유의하는 것이 중요 합니다. JSch는 명령 실행 결과로만 수행합니다.
Apache Mina SSHD에 대한 전체 문서는 프로젝트의 공식 GitHub 리포지토리에서 사용할 수 있습니다 .
4. 결론
이 기사에서는 사용 가능한 두 가지 Java 라이브러리인 JSch 및 Apache Mina SSHD를 사용하여 Java와 SSH 연결을 설정하는 방법을 설명했습니다. 또한 원격 서버에 명령을 전달하고 실행 결과를 얻는 방법을 보여주었습니다. 또한 GitHub 에서 전체 코드 샘플을 사용할 수 있습니다 .