Node.js通过SSH连接Debian服务器MySQL数据库失败求助
解决建议
以下是针对你遇到的Error: All configured authentication methods failed问题的排查和修复方案:
1. 确认环境变量加载正确性
先检查控制台打印的tunnelConfig和dbServer所有字段是否完全匹配DBeaver的配置,尤其是密码和用户名。环境变量未正确加载(比如拼写错误、未注入进程)是常见的隐性问题,确保process.env中的所有值都非空且准确。
2. 修正SSH隧道的端口转发参数
当通过SSH隧道连接时,从SSH服务器内部访问MySQL的地址应该是其本地地址(而非公网地址)。如果你的MySQL运行在SSH服务器本机,修改forwardConfig的dstHost为127.0.0.1:
const forwardConfig = { srcHost: '127.0.0.1', srcPort: 3307, // 改用本地未被占用的端口,避免和本地MySQL冲突 dstHost: '127.0.0.1', // 替换为SSH服务器上MySQL的本地地址 dstPort: dbServer.port };
3. 调整MySQL连接配置(适配stream模式)
使用ssh2的stream建立隧道后,mysql2不需要再指定host和port(因为stream已经是直接的连接通道),修改updatedDbServer的配置:
const updatedDbServer = { ...dbServer, stream, host: 'localhost', // 强制指向本地,或者直接删除host、port字段 port: null };
4. 适配SSH服务器的键盘交互认证
部分Debian服务器的SSH配置会启用键盘交互认证而非直接密码认证,而ssh2默认不会处理这种情况。添加键盘交互事件监听并开启tryKeyboard选项:
// 在sshClient.connect之前添加键盘交互处理 sshClient.on('keyboard-interactive', (name, instructions, _, prompts, finish) => { // 直接传入SSH密码完成交互 finish([tunnelConfig.password]); }); // 修改tunnelConfig,开启键盘交互尝试 const tunnelConfig = { host: process.env.DB_SSH_HOST, port: 22, username: process.env.DB_SSH_USER, password: process.env.DB_SSH_PASSWORD, tryKeyboard: true // 开启键盘交互支持 };
5. 检查SSH服务器的sshd配置
确保Debian服务器的/etc/ssh/sshd_config中开启了密码认证(如果使用密码登录):
# 编辑配置文件 sudo nano /etc/ssh/sshd_config # 确保以下配置项存在且未注释 PasswordAuthentication yes # 重启SSH服务 sudo systemctl restart sshd
修改后的完整代码示例
const mysql = require('mysql2'); const { Client } = require('ssh2'); const sshClient = new Client(); const dbServer = { user: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, database: process.env.DB_DATABASE } const tunnelConfig = { host: process.env.DB_SSH_HOST, port: 22, username: process.env.DB_SSH_USER, password: process.env.DB_SSH_PASSWORD, tryKeyboard: true }; const forwardConfig = { srcHost: '127.0.0.1', srcPort: 3307, dstHost: '127.0.0.1', dstPort: parseInt(process.env.DB_PORT) || 3306 }; const SSHConnection = new Promise((resolve, reject) => { console.log('DB Config:', dbServer); console.log('SSH Config:', tunnelConfig); sshClient.on('keyboard-interactive', (name, instructions, _, prompts, finish) => { finish([tunnelConfig.password]); }); sshClient.on('ready', () => { sshClient.forwardOut( forwardConfig.srcHost, forwardConfig.srcPort, forwardConfig.dstHost, forwardConfig.dstPort, (err, stream) => { if (err) return reject(err); const updatedDbServer = { ...dbServer, stream, host: 'localhost', port: null }; const connection = mysql.createConnection(updatedDbServer); connection.connect((error) => { if (error) { return reject(error); } resolve(connection); }); } ); }).on('error', (err) => { // 捕获SSH连接阶段的错误,便于排查 reject(`SSH Connection Error: ${err.message}`); }).connect(tunnelConfig); });
内容的提问来源于stack exchange,提问作者jansemrau
相关产品推荐
相关产品推荐

