本地Mac通过SSH连接MongoDB Atlas失败,求可行解决方案
本地Mac通过SSH连接MongoDB Atlas数据库的可行方案
问题背景
- MongoDB Atlas连接URI:
mongodb+srv://user:pass@cluster0.something.mongodb.net/ - 已将Ubuntu服务器IP(111.111.111.111)加入Atlas白名单,该服务器上用
mongosh可正常连接Atlas - 尝试两种方法均失败:
方法1:SSH隧道失败
执行命令:
ssh -L 27030:cluster0.something.mongodb.net:27017 -p 22 user@111.111.111.111
Compass连接URI:
mongodb://mongo_user:mongo_pass@localhost:27030/?authSource=admin
报错:channel 3: open failed: connect failed: No address associated with hostname
方法2:Golang+Nginx反向代理失败
Golang代码:
func main() { mongoURI := "mongodb+srv://user:pass@cluster0.something.mongodb.net/" sshHost := "111.111.111.111" sshPort := "22" sshUser := "user" sshPass := "pass" sshConfig := &ssh.ClientConfig{ User: sshUser, Auth: []ssh.AuthMethod{ ssh.Password(sshPass), }, HostKeyCallback: ssh.InsecureIgnoreHostKey(), } sshClient, err := ssh.Dial("tcp", fmt.Sprintf("%v:%v", sshHost, sshPort), sshConfig) if err != nil { log.Fatalf("Failed to dial SSH: %v", err) } defer sshClient.Close() mongoOptions := options.Client().ApplyURI(mongoURI) listener, err := sshClient.Listen("tcp", "localhost:27030") if err != nil { log.Fatalf("Failed to create SSH tunnel: %v", err) } defer listener.Close() mongoClient, err := mongo.Connect(nil, mongoOptions) if err != nil { log.Fatalf("Failed to connect to MongoDB: %v", err) } defer mongoClient.Disconnect(nil) fmt.Println("Connected to MongoDB over SSH") }
Nginx配置:
# 在nginx.conf的http块上方添加 stream { server { listen 27030; proxy_connect_timeout 1s; proxy_timeout 3s; proxy_pass stream_mongo_backend; } upstream stream_mongo_backend { server cluster0.something.mongodb.net:27017; } }
失败原因分析
- SSH隧道问题:
cluster0.something.mongodb.net是SRV记录,SSH隧道无法解析SRV域名背后的多节点集群,直接映射单个域名端口会导致地址解析失败。 - Golang+Nginx问题:Golang代码仅建立SSH连接和本地监听,未处理流量转发逻辑;Nginx的stream代理无法解析SRV记录,仅能代理单个固定地址,适配不了Atlas的多节点架构。
可行方案
方案1:SOCKS5代理转发(快速生效)
利用SSH的SOCKS5代理功能,让本地MongoDB请求通过Ubuntu服务器转发,自动解析SRV记录:
- 建立SOCKS5代理:
ssh -D 8080 -C -q -N user@111.111.111.111
参数说明:
-D 8080:在本地8080端口创建SOCKS5代理-C:压缩传输数据-q:静默模式-N:仅转发端口,不执行远程命令
- 配置本地客户端:
- Compass:进入
Advanced Options,勾选Use SOCKS5 Proxy,填写localhost:8080 - mongosh:
mongosh "mongodb+srv://user:pass@cluster0.something.mongodb.net/" --proxy socks5://localhost:8080
方案2:修改Golang代码实现隧道转发
通过自定义Dialer,让MongoDB客户端的所有连接请求都通过SSH隧道发送,自动适配SRV解析:
package main import ( "context" "fmt" "log" "net" "golang.org/x/crypto/ssh" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) func main() { mongoURI := "mongodb+srv://user:pass@cluster0.something.mongodb.net/" sshHost := "111.111.111.111" sshPort := "22" sshUser := "user" sshPass := "pass" // 配置SSH客户端 sshConfig := &ssh.ClientConfig{ User: sshUser, Auth: []ssh.AuthMethod{ ssh.Password(sshPass), }, HostKeyCallback: ssh.InsecureIgnoreHostKey(), } sshClient, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", sshHost, sshPort), sshConfig) if err != nil { log.Fatalf("SSH连接失败: %v", err) } defer sshClient.Close() // 自定义Dialer,通过SSH隧道建立MongoDB连接 mongoOptions := options.Client().ApplyURI(mongoURI).SetDialer(func(ctx context.Context, network, addr string) (net.Conn, error) { return sshClient.Dial(network, addr) }) // 连接并验证MongoDB ctx := context.Background() mongoClient, err := mongo.Connect(ctx, mongoOptions) if err != nil { log.Fatalf("MongoDB连接失败: %v", err) } defer mongoClient.Disconnect(ctx) if err := mongoClient.Ping(ctx, nil); err != nil { log.Fatalf("连接验证失败: %v", err) } fmt.Println("已通过SSH隧道连接MongoDB Atlas") }
方案3:部署MongoDB Atlas代理(推荐长期使用)
使用MongoDB官方提供的Atlas代理部署在Ubuntu服务器上,本地直接连接代理即可:
- 在Ubuntu服务器安装代理:
curl -fsSL https://atlas.mongodb.com/atlas-proxy/install.sh | bash
- 从MongoDB Atlas控制台获取代理配置文件(需开启集群代理功能)
- 启动代理:
atlas-proxy start --config /path/to/proxy-config.json
- 本地连接代理地址:
mongodb+srv://user:pass@localhost:27017/
内容的提问来源于stack exchange,提问作者Userak
相关产品推荐
相关产品推荐

