ssh2: не удается запустить сервер на узле js

Извините, если этот вопрос дублируется, но я не могу найти решение.

Кажется, моя проблема очень проста, но я не могу понять, что я делаю неправильно. Я хочу настроить ssh-клиент для подключения к нему и выполнить некоторые команды в оболочке. Итак, первое — я выбрал библиотеку ssh2 и попытался использовать следующий код.

var fs = require("fs");
var crypto = require("crypto");
var inspect = require("util").inspect;

var buffersEqual = require("buffer-equal-constant-time");
var ssh2 = require("ssh2");
var utils = ssh2.utils;

var pubKey = utils.genPublicKey(
  utils.parseKey(fs.readFileSync("user.pub")),
);

new ssh2.Server(
  {
    hostKeys: [fs.readFileSync("host.key")],
  },
  function(client) {
    console.log("Client connected!");

    client
      .on("authentication", function(ctx) {
        if (
          ctx.method === "password" &&
          // Note: Don't do this in production code, see
          // https://www.brendanlong.com/timing-attacks-and-usernames.html
          // In node v6.0.0+, you can use `crypto.timingSafeEqual()` to safely
          // compare two values.
          ctx.username === "foo" &&
          ctx.password === "bar"
        )
          ctx.accept();
        else if (
          ctx.method === "publickey" &&
          ctx.key.algo === pubKey.fulltype &&
          buffersEqual(ctx.key.data, pubKey.public)
        ) {
          if (ctx.signature) {
            var verifier = crypto.createVerify(ctx.sigAlgo);
            verifier.update(ctx.blob);
            if (verifier.verify(pubKey.publicOrig, ctx.signature))
              ctx.accept();
            else ctx.reject();
          } else {
            // if no signature present, that means the client is just checking
            // the validity of the given public key
            ctx.accept();
          }
        } else ctx.reject();
      })
      .on("ready", function() {
        console.log("Client authenticated!");

        client.on("session", function(accept, reject) {
          var session = accept();
          session.once("exec", function(accept, reject, info) {
            console.log(
              "Client wants to execute: " + inspect(info.command),
            );
            var stream = accept();
            stream.stderr.write("Oh no, the dreaded errors!\n");
            stream.write("Just kidding about the errors!\n");
            stream.exit(0);
            stream.end();
          });
        });
      })
      .on("end", function() {
        console.log("Client disconnected");
      });
  },
).listen(0, "127.0.0.1", function() {
  console.log("Listening on port " + this.address().port);
});

Я поместил его в файл index.js. Перед использованием этого кода:

  1. Настроил пару ключей командой ssh-keygen -t rsa -b 4096, получил 2 ключа ssh.pub и ssh;
  2. Затем переименован в user.pub и host.key;
  3. После этого я сделал ssh-add host.key. Ответ был Identity added: host.key (host.key). Кажется, все в порядке.

Я запустил node index.js и получил следующую ошибку:

throw new Error('Missing passphrase for encrypted private key')

Что я сделал не так? Может быть, неправильная команда для создания пары ключей? Я буду очень признателен, если вы мне поможете.


person Merge-pony    schedule 09.08.2018    source источник
comment
Что находится в index.js?   -  person AKX    schedule 09.08.2018
comment
файл я положил код   -  person Merge-pony    schedule 09.08.2018
comment
Какая строка выдает ошибку? Вы можете попытаться подключиться, или он просто сразу вылетает?   -  person AKX    schedule 09.08.2018
comment
@АКХ /node_modules/ssh2/lib/server.js:57 . Сервер не запущен.   -  person Merge-pony    schedule 09.08.2018
comment
Просто чтобы быть уверенным: вы не вводили парольную фразу для сгенерированного ключа, верно?   -  person AKX    schedule 09.08.2018
comment
@AKX нет, я ввел его оба раза   -  person Merge-pony    schedule 09.08.2018
comment
О, тогда ошибка, которую вы получаете, очевидна. Вам также нужно будет передать это при инициализации вашего ssh2.Server. Смотрите редактирование моего ответа.   -  person AKX    schedule 09.08.2018


Ответы (1)


Таким образом, проблема связана с тем, что вы (как вы признали в комментариях) используете ключ хоста, защищенный паролем. ssh2, естественно, тоже нуждается в кодовой фразе.

В документации говорится

hostKeys – массив. Массив буферов/строк, содержащих закрытые ключи хоста, или объекты в формате { key: <Buffer/string>, passphrase: <string> } для зашифрованных закрытых ключей. (Необходимый)

поэтому постарайтесь

{
  hostKeys: [
    {
      key: fs.readFileSync('...'),
      passphrase: 'the-passphrase-you-used',
    },
  ],
}

Без паролей

Я не могу воспроизвести эту проблему (с более простым кодом):

$ yarn add ssh2
$ cat > index.js

var fs = require("fs");
var crypto = require("crypto");
var inspect = require("util").inspect;

var ssh2 = require("ssh2");
var utils = ssh2.utils;

new ssh2.Server(
  {
    hostKeys: [fs.readFileSync("host.key")],
  },
  function(client) {
    console.log("Client connected!");

    client
      .on("authentication", function(ctx) {
        ctx.accept();
      })
      .on("ready", function() {
        console.log("Client authenticated!");
        client.on("session", function(accept, reject) {
          var session = reject();
          console.log("Client session rejected.");
        });
      })
      .on("end", function() {
        console.log("Client disconnected");
      });
  },
).listen(0, "127.0.0.1", function() {
  console.log("Listening on port " + this.address().port);
});

$ ssh-keygen -t rsa -b 1024
Generating public/private rsa key pair.
Enter file in which to save the key: ./host
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./host.
Your public key has been saved in ./host.pub.
$ mv host host.key
$ node index.js
Listening on port 52182
Client connected!
Client authenticated!
Client session rejected.
Client disconnected

(где была моя попытка подключения по ssh :)

$ ssh [email protected] -p 52182
channel 0: open failed: administratively prohibited:
Connection to 127.0.0.1 closed.
~ $
person AKX    schedule 09.08.2018
comment
большое спасибо! Это сработало! И как я могу запустить сервер без парольной фразы? - person Merge-pony; 09.08.2018
comment
Я не уверен, что вы имеете в виду. Ваш ключ хоста должен быть либо без фразы-пароля, либо фраза-пароль должна быть (каким-то образом) доступной для кода сервера. - person AKX; 09.08.2018
comment
да, конечно! Но я имею в виду, что если в примерах ssh2 пакета отсутствует парольная фраза в hostKeys, то, возможно, ее можно было бы предоставить другим способом? Если да, то можете ли вы сказать мне, как? (кроме, очевидно, passphrase: 'the-passphrase-you-used') - person Merge-pony; 09.08.2018
comment
Вы можете прочитать его из файла, вы можете передать его как переменную среды ... Однако большинство ключей хоста SSH не защищены паролем. Представьте, что вам придется физически вводить пароль на сервере каждый раз, когда он загружается, прежде чем вы сможете подключиться по SSH? - person AKX; 10.08.2018