Node.js通过node-ssh连接HP-UX服务器报read ECONNRESET认证失败
NodeSSH连接HP-UX服务器报ECONNRESET错误解决方案
问题现象
连接本地网络自托管HP-UX服务器时触发连接重置错误,报错信息如下:
Hello world Connected to Nemesis true rejected: Error: read ECONNRESET at TCP.onStreamRead (node:internal/stream_base_commons:217:20) { errno: -4077, code: 'ECONNRESET', syscall: 'read', level: 'client-socket' } node:internal/process/promises:279 triggerUncaughtException(err, true /* fromPromise */); ^ Error: read ECONNRESET at TCP.onStreamRead (node:internal/stream_base_commons:217:20) { errno: -4077, code: 'ECONNRESET', syscall: 'read', level: 'client-socket' }
问题复现所用测试代码:
console.log('Hello world'); const { NodeSSH } = require('node-ssh'); const ssh = new NodeSSH(); ssh.connect({ host: "server", username: "admin account", password: "password" }).then(console.log("Connected to Nemesis")) console.log(ssh.isConnected()); ssh.exec('hh_client', ['--json'], { cwd: '/', stream: 'stdout', options: { pty: true } }).then(fulfilled => { console.log("fulfilled:", fulfilled) }).catch(rejected => { console.log("rejected:", rejected) })
已确认的前置信息:
- 修改服务器IP测试时会提示找不到服务器,基础网络连通性正常
- 输入错误用户名/密码时触发完全相同的报错,账号密码参数未被正确用于认证
- 代码中
exec调用逻辑复制自node-ssh模块npm官方文档示例 - 服务器为接手的存量HP-UX环境,
.ssh目录下已有存量密钥配置,不能覆盖原有内容 - 使用系统终端执行
ssh user@server命令,输入相同用户名密码可以正常连接,账号拥有服务器完整操作权限
根因定位
- 第一处问题是异步逻辑编写错误:
ssh.connect()是异步返回Promise的方法,原代码中.then(console.log("Connected to Nemesis"))的写法会在调用connect时立刻执行日志打印,不会等待连接握手完成,后续的isConnected()检查、exec()命令调用都是在SSH连接还未建立完成时触发的。 - 第二处问题是算法兼容问题:存量HP-UX环境搭载的OpenSSH版本普遍较低,默认仅支持较早版本的密钥交换、加密、主机密钥算法,node-ssh底层依赖的ssh2库默认启用的算法列表不包含这些老旧算法,连接会在算法协商阶段被服务端直接重置,根本不会走到用户名密码认证环节,这也是输入错误账号密码也报相同错误的核心原因。
修复方案
- 修正异步调用逻辑,必须等待
connect方法的Promise状态变更为成功后,再执行后续的状态检查、命令执行操作。 - 在connect配置中显式添加兼容HP-UX老版本SSH的算法列表,该方案使用密码认证,完全不需要修改服务器
.ssh目录下的任何存量文件,不会影响原有密钥认证配置。
修正后的可运行代码:
const { NodeSSH } = require('node-ssh'); const ssh = new NodeSSH(); async function runCommand() { try { // 建立SSH连接 await ssh.connect({ host: "替换为实际服务器地址", username: "替换为实际登录账号", password: "替换为实际登录密码", // 兼容HP-UX老版本SSH的算法配置 algorithms: { kex: [ 'diffie-hellman-group1-sha1', 'diffie-hellman-group14-sha1', 'diffie-hellman-group-exchange-sha1' ], cipher: [ 'aes128-cbc', '3des-cbc', 'aes192-cbc', 'aes256-cbc' ], serverHostKey: [ 'ssh-rsa', 'ssh-dss' ], hmac: [ 'hmac-sha1', 'hmac-md5' ] } }) console.log("连接成功,当前连接状态:", ssh.isConnected()) // 执行目标命令 const execResult = await ssh.exec('hh_client', ['--json'], { cwd: '/', stream: 'stdout', options: { pty: true } }) console.log("命令执行结果:", execResult) } catch (err) { console.log("操作异常:", err) } finally { // 用完释放连接 ssh.dispose() } } runCommand()
- 如果添加上述算法配置后仍连接失败,可以在本地终端执行
ssh -vvv user@实际服务器地址,查看终端正常连接时协商成功的kex、cipher、serverHostKey、hmac算法值,将对应算法添加到上述algorithms配置数组的最前端即可。
注意:上述算法列表包含部分已被认定为不安全的老旧算法,仅适用于内网隔离的存量HP-UX环境,若后续服务器SSH服务完成升级,建议及时移除这些老旧算法配置。
内容的提问来源于stack exchange,提问作者Craig
相关产品推荐
相关产品推荐

