You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS通过SSH Tunnel连接AWS RDS MySQL超时问题求助

Node.js 通过 SSH Tunnel 连接 AWS RDS MySQL 超时问题求助

我和伙伴合作开发项目,后端采用Node.js,数据库使用AWS RDS MySQL,目前核心问题是无法在Node.js环境中通过SSH Tunnel正常与数据库建立通信。以下是我整理的配置代码及API调用报错信息,恳请提供帮助或建议!

SSH Tunnel配置

const { createTunnel } = require ('tunnel-ssh');
const fs = require('fs');
const path = require('path');
require('dotenv').config();

async function createSSHTunnel(srcAddr = process.env.SSH_HOST, srcPort = process.env.SSH_PORT) {
    const tunnelOptions = {
        autoClose: true,
    };

    const serverOptions = {
        port: srcPort,
    };

    const sshOptions = {
        host: process.env.SSH_HOST,
        port: parseInt(process.env.SSH_PORT),
        username: process.env.SSH_User,
        privateKey: fs.readFileSync(path.join(__dirname, 'JD KeyPair.pem')),
    };

    const forwardOptions = {
        srcAddr: srcAddr,
        srcPort: srcPort,
        dstAddr: process.env.DB_Host,
        dstPort: parseInt(process.env.DB_Port),
    };

    try {
        await createTunnel(
            tunnelOptions,
            serverOptions,
            sshOptions,
            forwardOptions
        );
    } catch (error) {
        if (error.code === "EADDRINUSE") {
            // 假设该端口仅被SSH隧道占用,复用现有连接
            console.log(`复用${srcAddr}:${srcPort}上已有的SSH隧道。`);
            return { srcAddr, srcPort };
        } else {
            throw error;
        }
    }
    
    console.log(`SSH隧道已成功创建在${srcAddr}:${srcPort}。`);
    
    return { srcAddr, srcPort };
}

module.exports = { createSSHTunnel };

数据库配置

const { createPool } = require('mysql2/promise');
const { createSSHTunnel } = require ('./sshTunnel');
require('dotenv').config();

const { srcAddr, srcPort } = createSSHTunnel();

const db = createPool({
    host: process.env.DB_Host,
    port: process.env.DB_Port,
    user: process.env.DB_User,
    password: process.env.DB_Pass,
    database: process.env.DB_Data,
    waitForConnections: true,
    connectionLimit: 10,
    queueLimit: 0,
});

module.exports = db;

API调用示例

router.post('/retrieveCardInfo', async (req, res) => {
  const cardID = req.body.CardID.CardID;

  try {
    const uploadCardStatus = await db.query('SELECT * FROM cardstorage WHERE cardID = ?', [cardID]);

    if (typeof uploadCardStatus[0][0] !== 'undefined') {
      return res.send(uploadCardStatus[0][0]);
    }
    return res.json({errorMessage: "Card Not Found"});
  }
  catch (err) {
    return res.json({ errorMessage: 'A Server Error Occured!' });
  }
});

API执行报错信息

code: 'ETIMEDOUT',
  errno: undefined,
  sql: undefined,
  sqlState: undefined,
  sqlMessage: undefined

问题排查及解决方案

  1. 异步初始化未等待(核心问题)
    createSSHTunnel是异步函数,但数据库配置中直接解构赋值未使用await,导致连接池在隧道建立前就尝试连接RDS,必然超时。修改数据库配置:
const { createPool } = require('mysql2/promise');
const { createSSHTunnel } = require ('./sshTunnel');
require('dotenv').config();

let db;
// 用立即执行异步函数确保隧道建立后再初始化连接池
(async () => {
  try {
    const { srcAddr, srcPort } = await createSSHTunnel();
    db = createPool({
        host: srcAddr, // 连接隧道本地监听地址,而非直接连RDS
        port: srcPort,
        user: process.env.DB_User,
        password: process.env.DB_Pass,
        database: process.env.DB_Data,
        waitForConnections: true,
        connectionLimit: 10,
        queueLimit: 0,
    });
    console.log('数据库连接池已初始化');
  } catch (err) {
    console.error('初始化数据库连接池失败:', err);
  }
})();

module.exports = db;
  1. SSH隧道监听地址修正
    forwardOptions中的srcAddr应设为'localhost'或'127.0.0.1'(本地监听),而非SSH_HOST,否则可能因监听公网地址导致无法访问。修改createSSHTunnel的默认参数:
async function createSSHTunnel(srcAddr = 'localhost', srcPort = process.env.SSH_PORT) {
  // ... 其余代码不变
}
  1. 验证网络连通性
  • 先用SSH命令手动连接堡垒机,再从堡垒机连接RDS,确认网络通路:
    ssh -i "JD KeyPair.pem" ${SSH_User}@${SSH_HOST}
    # 登录堡垒机后执行
    mysql -h ${DB_Host} -P ${DB_Port} -u ${DB_User} -p
    
  • 检查堡垒机安全组是否允许Node.js服务器IP访问22端口,RDS安全组是否允许堡垒机内网IP访问3306端口。
  1. 私钥文件权限
    在Linux/macOS环境下,确保私钥文件JD KeyPair.pem权限为600,否则SSH会拒绝使用:
chmod 600 "JD KeyPair.pem"
  1. 依赖版本兼容性
    若tunnel-ssh版本存在参数兼容问题,可考虑改用ssh2库手动实现隧道,控制更精细。

内容的提问来源于stack exchange,提问作者JonD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 23:23:11