Перейти к основному содержимому

SSH-соединение с Java

· 5 мин. чтения

1. Введение

SSH , также известный как Secure Shell или Secure Socket Shell, представляет собой сетевой протокол, который позволяет одному компьютеру безопасно подключаться к другому компьютеру через незащищенную сеть. В этом руководстве мы покажем, как установить соединение с удаленным SSH-сервером с помощью Java с помощью библиотек JSch и Apache MINA SSHD .

В наших примерах мы сначала откроем соединение SSH, затем выполним одну команду, прочитаем вывод и запишем его в консоль и, наконец, закроем соединение SSH. Мы постараемся максимально упростить пример кода.

2. ЙШ

JSch — это Java-реализация SSH2, которая позволяет нам подключаться к SSH-серверу и использовать переадресацию портов, переадресацию X11 и передачу файлов. Кроме того, он распространяется под лицензией в стиле BSD и предоставляет нам простой способ установить SSH-соединение с Java.

Во-первых, давайте добавим зависимость JSch Maven в наш файл pom.xml :

<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>

2.1. Реализация

Чтобы установить SSH-соединение с помощью JSch, нам нужны имя пользователя, пароль, 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 автоматически добавит новый ключ хоста в список известных хостов.
  • Compression.s2c — указывает, использовать ли сжатие для потока данных от сервера к нашему клиентскому приложению. Доступные значения: zlib и none , где второе значение по умолчанию.
  • Compression.c2s — указывает, использовать ли сжатие для потока данных в направлении клиент-сервер. Доступные значения: zlib и none , где второе значение по умолчанию.

Важно закрыть сеанс и канал SFTP после завершения связи с сервером, чтобы избежать утечек памяти .

3. Апач МИНА SSHD

Apache MINA SSHD обеспечивает поддержку SSH для приложений на основе Java. Эта библиотека основана на Apache MINA, масштабируемой и высокопроизводительной асинхронной библиотеке ввода-вывода.

Давайте добавим зависимость Apache Mina SSHD Maven :

<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>2.5.1</version>
</dependency>

3.1. Реализация

Давайте посмотрим на пример кода подключения к SSH-серверу с помощью Apache MINA SSHD:

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. Сначала мы устанавливаем соединение с сервером SSH, используя экземпляр класса SshClient . Если мы инициализируем его с помощью SshClient.setupDefaultClient(), мы сможем работать с экземпляром, который имеет конфигурацию по умолчанию, подходящую для большинства случаев использования. Это включает в себя шифрование, сжатие, MAC, обмен ключами и подписи.

После этого мы создадим ClientChannel и присоединим к нему ByteArrayOutputStream , чтобы использовать его как поток ответа. Как мы видим, SSHD требует определенных тайм-аутов для каждой операции. Это также позволяет нам определить, как долго он будет ждать ответа сервера после передачи команды с помощью метода Channel.waitFor() .

Важно отметить, что SSHD запишет полный вывод консоли в поток ответов. JSch сделает это только с результатом выполнения команды.

Полная документация по Apache Mina SSHD доступна в официальном репозитории проекта на GitHub .

4. Вывод

В этой статье показано, как установить SSH-соединение с Java с помощью двух доступных библиотек Java — JSch и Apache Mina SSHD. Мы также показали, как передать команду на удаленный сервер и получить результат выполнения. Кроме того, полные примеры кода доступны на GitHub .