首页 > 解决方案 > ssh2:无法在节点 js 上运行服务器

问题描述

如果这个问题重复,我很抱歉,但我找不到解决方案。

似乎我的问题很简单,但我不明白我做错了什么。我想设置 ssh 客户端来连接它并在 shell 中执行一些命令。所以第一件事 - 我选择了 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.pubssh
  2. 然后重命名为user.puband 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')

我做错了什么?也许创建密钥对的命令错误?如果您能帮助我,我将不胜感激。

标签: javascriptnode.jslibssh2ssh2-sftp

解决方案


因此,问题源于您(正如您在评论中承认的那样)正在使用受密码保护的主机密钥。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 foo@127.0.0.1 -p 52182
channel 0: open failed: administratively prohibited:
Connection to 127.0.0.1 closed.
~ $

推荐阅读