通过nodejs以编程方式连接到EC2实例时ECONNREFUSED,在shell中工作

问题描述 投票:0回答:1

我写了一些js代码,在指定区域创建一个实例。

它创建一个新的安全组和私钥文件,然后使用这些设置创建实例。

安全组设置为允许来自任何地方的 ssh 流量。

async function authorizeSecurityGroupIngress(ec2, groupId) {
  try {
    const params = {
      GroupId: groupId,
      IpPermissions: [
        {
          IpProtocol: "tcp",
          FromPort: 22, // SSH
          ToPort: 22,
          IpRanges: [{ CidrIp: "0.0.0.0/0" }], // Allow SSH access from anywhere 
        }
      ],
    };

    await ec2.authorizeSecurityGroupIngress(params).promise();
    console.log("Ingress rule added to security group.");
  } catch (err) {
    console.error("Error authorizing ingress:", err);
    throw err;
  }
}

实例运行后:

function waitForInstanceRunning(ec2, instanceId) {
  const params = {
    InstanceIds: [instanceId],
  };

  return new Promise((resolve, reject) => {
    ec2.waitFor("instanceRunning", params, (err, data) => {
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    });
  });
}

我使用 ssh2 ssh 进入实例并执行命令。

// modify permissions of the file to 600
        chmod600(pemFilePath).then(()=>{
          const connSettings = {
            host: publicIpAddress,
            port: 22, // Standard SSH port
            username: 'ubuntu',
            privateKey: require('fs').readFileSync(pemFilePath) 
          };
          const conn = new Client();
          conn.on('ready', () => {
            console.log('SSH connection established');

            conn.exec(command, (err, stream) => {
              if (err) throw err;
              stream.on('close', (code, signal) => {
                console.log('Stream closed');
                conn.end();
              }).on('data', (data) => {
                console.log('STDOUT: ' + data);
              }).stderr.on('data', (data) => {
                console.log('STDERR: ' + data);
              });
            });
          }).connect(connSettings);

          conn.on('error', (err) => {
            console.error('Error: ', err);
          });
        })

publicIpAdress
是正确的,
pemFilePath
是正确的,chmod600功能确实有效(之前都测试过)

代码中的所有内容都有效:

Key pair created: dep_kp_97zlncl1yf9
Private key uploaded to S3 bucket 'deploykps' with key keyPairs/dep_kp_97zlncl1yf9.pem
Local private key file dep_kp_97zlncl1yf9.pem deleted.
Security group created: sg-0144a5cfc4765cf2a
Ingress rule added to security group.
Instance created: i-05f7c65f29b6b714e
Instance is running: i-05f7c65f29b6b714e
sending test command `echo 'hello world' > ~/test.txt`
Starting command execution on instance i-05f7c65f29b6b714e

`echo 'hello world' > ~/test.txt`
Found public IP 54.241.142.163
PEM file downloaded from S3 bucket 'deploykps' with key keyPairs/dep_kp_97zlncl1yf9.pem
Permissions set to 600 successfully for dep_kp_97zlncl1yf9.pem
Error:  Error: connect ECONNREFUSED 54.241.142.163:22
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1595:16) {
  errno: -111,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '54.241.142.163',
  port: 22,
  level: 'client-socket'
}

ChatGPT 表示问题可能是以下任一情况:

    EC2 实例上未启用 ssh -> 不可能,否则我自己的 shell 中的后续 ssh 也无法工作
  • IP 地址/主机不正确 -> 与之前相同
  • 防火墙/网络配置 -> 与之前相同 + 我仔细检查了所有安全组和 ACL 规则...两者都允许来自任何地方的 SSH 流量 (0.0.0.0/0)
  • ssh 密钥验证 -> 没问题,我的 shell 中使用了相同的密钥
(基本上chatGPT没啥用)

我尝试过最新的节点版本(20.12.1)和新的 ssh2 安装,同样的问题。 还在多种环境中进行了尝试(Replit,AWS实例,目前无法访问我的个人机器,但就运行方式而言,它应该与AWS实例相同)

AWS 实例是 t2.micro

如果您想要完整的代码作为参考,这里是:

https://sisyphian-game.s3.us-west-2.amazonaws.com/index.js
(存储桶名称并不重要,只是我闲置的一个公共存储桶)

也欢迎有关从 NodeJS 在 ec2 实例上运行 bash 命令的更简单方法的建议。

node.js amazon-web-services amazon-ec2 ssh
1个回答
0
投票
这可能是显而易见的,但只是因为你没有提到它:

您是否在 EC2 实例中检查了 sshd 配置文件以允许来自所有网络接口中的所有 ip 的连接以及配置的身份验证方法? (对于最后一项,您通常需要在 .ssh/authorized_keys 中为目标用户添加密钥)。

您还应该验证 EC2 实例中的防火墙规则(如果启用)。

希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.