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

本地Node.js通过SSH隧道连接AWS RDS Postgres的问题求助

AWS RDS SSH隧道本地连接问题解决方案

问题背景

我有一个运行在EC2实例上的Node.js应用,可成功连接AWS RDS Postgres数据库并执行SQL语句返回结果。现在希望在本地机器运行该应用,尝试使用EC2的密钥对创建SSH隧道:

ssh -i ec2-db-keypair.pem -N -L localhost:8080:database-test-1.XXX.eu-west-2.rds.amazonaws.com:5432 ec2-user@ec2-XXX.eu-west-2.compute.amazonaws.com

本地Node服务监听8081端口,访问/db路由时使用以下连接池配置(该配置在EC2实例上可正常工作):

server.listen({ port: 8081 }, (err, address) => {
  if (err) {
    console.error(err);
    process.exit(1);
  }
  console.log(`Server listening at ${address}`);
});

server.get("/db", async (request, reply) => {
  console.log("connect to db using slonik");

  const pem = fs
    .readFileSync(path.join(__dirname, "../../eu-west-2-bundle.pem"))
    .toString();

  const pool = createPool(
// ec2 instance instead of localhost:8080 I use: database-test-1.XXX.eu-west-2.rds.amazonaws.com:5432
    `postgresql://postges:mydbpassword@localhost:8080/postgres`,
    {
      ssl: {
        ca: pem,
        rejectUnauthorized: true,
      },
    }
  );

  pool.connect(async (connection) => {
    try {
      const resultNodejsMyTableRows = await connection.query(
        sql`SELECT * FROM nodejs_mytable ORDER BY id ASC`
      );
      console.log("nodejs_mytable=", { resultNodejsMyTableRows });
    } catch (err) {
      console.log(err);
    }
  });

  return "look at console for responses\n";
});

本地运行时出现错误:

Hostname/IP does not match certificate's altnames: Host: localhost. is not in the cert's altnames: DNS:database-test-1.XXX.eu-west-2.rds.amazonaws.com

SSH隧道用法是否正确?

你的SSH隧道命令本身是正确的,它能将本地8080端口的流量转发到EC2实例,再由EC2转发至RDS数据库的5432端口。问题出在Node.js连接数据库时的SSL证书验证逻辑。

错误原因

AWS RDS的SSL证书是绑定到其专属域名(database-test-1.XXX.eu-west-2.rds.amazonaws.com)的,而你本地连接时使用的是localhost:8080,SSL验证过程中会检查连接的主机名是否与证书中的域名匹配,因此出现了不匹配的错误。

修正方案

方法1:修改本地hosts映射(推荐)

通过把RDS域名映射到本地回环地址,让SSL验证认为你连接的是真实RDS域名,同时流量通过SSH隧道转发:

  • 打开本地hosts文件:
    • Windows:C:\Windows\System32\drivers\etc\hosts
    • macOS/Linux:/etc/hosts
  • 添加一行映射:
    127.0.0.1 database-test-1.XXX.eu-west-2.rds.amazonaws.com
    
  • 修改Node.js的数据库连接字符串,将localhost:8080换回RDS原域名:
    `postgresql://postges:mydbpassword@database-test-1.XXX.eu-west-2.rds.amazonaws.com:8080/postgres`
    

方法2:临时关闭SSL主机名验证(仅本地调试用)

如果只是临时本地调试,可以跳过SSL主机名验证,但绝对不要在生产环境使用:
修改连接池的SSL配置,添加checkServerIdentity: () => undefined:

const pool = createPool(
  `postgresql://postges:mydbpassword@localhost:8080/postgres`,
  {
    ssl: {
      ca: pem,
      rejectUnauthorized: true,
      checkServerIdentity: () => undefined // 跳过主机名验证
    },
  }
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:34:50