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

本地通过EC2隧道连接AWS DocDB报错,求排查方案

问题描述

我有一台EC2实例(EC2_VM),可从该实例连接MongoDB(MONGO_HOST)。使用以下Python代码通过SSH隧道从本地连接:

with sshtunnel.open_tunnel(
    (EC2_VM, 22),
    ssh_username="ec2-user",
    ssh_pkey=EC2_KEY,
    remote_bind_address=(MONGO_HOST, 27017),
    local_bind_address=("0.0.0.0", 27017),
) as tunnel:
    print(tunnel.local_bind_port)    

    # list database names
    client = MongoClient(
        "mongodb://%s:%s@%s" % (MONGO_USER, MONGO_PASSWORD, "127.0.0.1"),
        port=tunnel.local_bind_port,
    )
    names = client.list_database_names()
    print(names)

运行后出现超时错误:

File "/lib/python3.11/site-packages/pymongo/topology.py", line 269, in _select_servers_loop
    raise ServerSelectionTimeoutError(
pymongo.errors.ServerSelectionTimeoutError: 127.0.0.1:27017: timed out, Timeout: 30s, Topology Description: <TopologyDescription id: 6530a0a24577402c25f1997e, topology_type: Unknown, servers: [<ServerDescription ('127.0.0.1', 27017) server_type: Unknown, rtt: None, error=NetworkTimeout('127.0.0.1:27017: timed out')>]>

隧道看似成功建立,但无法连接MongoDB。另外想请教:有AWS DocDB部署经验的话,如何从本地通过脚本连接?MongoDB Compass的GUI隧道功能可正常使用,但pymongo脚本无法连接,盼解答。


解决方案

一、EC2 SSH隧道连接MongoDB的问题排查

1. 修复端口匹配问题

你设置了local_bind_address=("0.0.0.0", 27017),但如果本地27017端口已被占用,隧道会自动分配其他随机端口。代码中打印了tunnel.local_bind_port,但连接时仍指定27017,导致端口不匹配。

修正后的代码(自动分配端口):

with sshtunnel.open_tunnel(
    (EC2_VM, 22),
    ssh_username="ec2-user",
    ssh_pkey=EC2_KEY,
    remote_bind_address=(MONGO_HOST, 27017),
    # 移除local_bind_address,让系统自动分配可用端口
) as tunnel:
    print(f"本地绑定端口: {tunnel.local_bind_port}")    

    client = MongoClient(
        f"mongodb://{MONGO_USER}:{MONGO_PASSWORD}@127.0.0.1:{tunnel.local_bind_port}"
    )
    names = client.list_database_names()
    print(names)

2. 验证EC2到MongoDB的连通性

登录EC2实例,执行以下命令确认EC2能访问MongoDB的27017端口:

telnet MONGO_HOST 27017
# 或
nc -zv MONGO_HOST 27017

如果这一步不通,说明EC2安全组或MongoDB防火墙限制了访问,需先调整规则打通这层连接。

3. 开启隧道调试日志排查

添加日志输出,确认隧道是否真的成功建立:

import logging
logging.basicConfig(level=logging.DEBUG)

with sshtunnel.open_tunnel(
    (EC2_VM, 22),
    ssh_username="ec2-user",
    ssh_pkey=EC2_KEY,
    remote_bind_address=(MONGO_HOST, 27017),
) as tunnel:
    # 原有连接代码

通过日志可排查SSH连接、远程端口绑定是否存在异常。


二、本地脚本连接AWS DocDB的方法

DocDB兼容MongoDB协议,但强制要求SSL连接,需注意以下配置:

1. 完整连接脚本示例

import sshtunnel
from pymongo import MongoClient

# 替换为你的实际参数
EC2_VM = "ec2-xxx-xxx-xxx-xxx.compute-1.amazonaws.com"
EC2_KEY = "/path/to/your/ec2-key.pem"
DOCDB_HOST = "docdb-cluster-xxx.cluster-xxx.us-east-1.docdb.amazonaws.com"
DOCDB_USER = "admin"
DOCDB_PASSWORD = "your-password"
DOCDB_PORT = 27017
CA_CERT_PATH = "/path/to/rds-combined-ca-bundle.pem"  # AWS官方RDS CA证书路径

with sshtunnel.open_tunnel(
    (EC2_VM, 22),
    ssh_username="ec2-user",
    ssh_pkey=EC2_KEY,
    remote_bind_address=(DOCDB_HOST, DOCDB_PORT),
) as tunnel:
    client = MongoClient(
        f"mongodb://{DOCDB_USER}:{DOCDB_PASSWORD}@127.0.0.1:{tunnel.local_bind_port}",
        ssl=True,
        ssl_ca_certs=CA_CERT_PATH,
        ssl_match_hostname=False  # 生产环境建议开启,调试阶段可临时关闭
    )
    # 测试连接
    print(client.list_database_names())

2. 关键注意事项

  • CA证书获取:从AWS官网下载RDS组合CA证书,保存到本地指定路径。
  • 安全组配置:确保DocDB的安全组允许EC2实例的IP访问27017端口。
  • 版本兼容性:DocDB仅兼容特定版本的MongoDB,需确保pymongo版本与DocDB版本匹配(例如DocDB 5.0兼容pymongo 4.x)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 01:48:29