通过堡垒机双层SSH隧道访问AWS私有PostgreSQL数据库的Python实现问题
私有PostgreSQL数据库SSH隧道访问配置方案
原代码错误原因
- 参数配置逻辑错误:
remote_bind_address用于指定要转发的目标服务地址,你填了私有Linux实例的SSH端口22,和你要访问的PostgreSQL服务无关 - 缺少两级SSH跳转配置:你只配置了本地到堡垒机的隧道,没有完成堡垒机到私有Linux实例的跳转,无法触达数据库
- 数据库连接地址配置错误:你直接在
create_engine中填写了私有RDS的地址,这个地址属于内网地址,本地网络无法解析,因此抛出could not translate host name to address报错
修正后完整实现
你的访问链路为「本地设备 → 堡垒机 → 私有Linux实例 → PostgreSQL数据库」,需要配置两级SSH隧道,将数据库端口转发到本地后再用sqlalchemy连接,示例代码如下:
from sshtunnel import SSHTunnelForwarder from sqlalchemy import create_engine # 第一级隧道:本地连接堡垒机,转发私有实例的SSH端口到本地 with SSHTunnelForwarder( # 堡垒机公网地址+SSH默认端口22 ('xxx-x-xx-xx-xxx.us-west-2.compute.amazonaws.com', 22), ssh_username="ubuntu", ssh_pkey="fourmm.pem", # 转发目标为私有Linux实例的SSH端口 remote_bind_address=('私有Linux实例的内网地址', 22) ) as bastion_tunnel: # 第二级隧道:通过堡垒机转发的端口连接私有实例,转发数据库端口到本地 with SSHTunnelForwarder( ('127.0.0.1', bastion_tunnel.local_bind_port), ssh_username="私有Linux实例的SSH用户名", ssh_pkey="fourmm.pem", # 此处填写私有实例上访问PostgreSQL的地址和端口: # 若数据库部署在私有实例本地,填 ('127.0.0.1', 5432) # 若为私有RDS,填你原代码中的RDS端点地址,注意修正原地址中的拼写错误us-wesr-为正确区域 remote_bind_address=('PostgreSQL数据库访问地址', 5432) ) as db_tunnel: print("****SSH Tunnel Established****") # sqlalchemy直接连接本地转发后的端口即可 engine = create_engine( f"postgresql://postgres:你的数据库密码@127.0.0.1:{db_tunnel.local_bind_port}/postgres", echo=True, future=True ) # 测试连接 with engine.connect() as conn: print(conn.scalar("SELECT version();"))
注意事项
- 确认PEM文件权限为600,否则SSH连接会被拒绝
- 确认堡垒机安全组放行了本地IP的22端口访问权限
- 确认私有Linux实例安全组放行了堡垒机内网IP的22端口访问权限
- 确认PostgreSQL数据库安全组放行了私有Linux实例内网IP的5432端口访问权限
- 若你的堡垒机本身有权限直接访问PostgreSQL数据库,可以省略第二级隧道,直接将
remote_bind_address配置为数据库地址和端口,sqlalchemy连接本地转发端口即可
内容的提问来源于stack exchange,提问作者Robert Marciniak
相关产品推荐
相关产品推荐

