将 Heroku App 连接到 Atlas MongoDB 云服务
Posted
技术标签:
【中文标题】将 Heroku App 连接到 Atlas MongoDB 云服务【英文标题】:Connecting Heroku App to Atlas MongoDB Cloud service 【发布时间】:2019-09-10 03:21:15 【问题描述】:预测问题:我是否需要在 Heroku 上获得 SSL 支持才能在 Heroku 和 Atlas MongoDB Cloud 之间建立连接使用 SSL? (TSL/SSL 连接是requirement 以访问 Atlas MongoDB Cloud 服务)。
我正在尝试将我用 node.js 编写的 Heroku 应用程序连接到托管在 Atlas MongoDB Cloud 上的集群。
我当前的数据库托管在 mLab(作为 Heroku 插件),用于通过 mongoose 访问集群的 MongoDB URI 是(使用 xxx 省略机密信息):
MONGODB_URI="mongodb://xxx:xxx@xxx-a0.mlab.com:23266,xxx-a1.mlab.com:xxx/xxx?replicaSet=rs-xxx"
现在我已将数据从 mLab 迁移到 Atlas MongoDB Cloud,我目前正在使用 URI 访问集群:
MONGODB_URI="mongodb://xxx:xxx@cluster0-shard-xxx.mongodb.net:xxx,cluster0-shard-xxx.mongodb.net:xxx,cluster0-shard-xxx.mongodb.net:xxx/xxx?replicaSet=xxx&ssl=true&authSource=admin"
在我的机器上本地运行我的 Heroku 应用程序时,我可以毫无问题地访问数据库。我还可以使用 mongo shell 连接到集群。
但是,在 Heroku 中运行应用程序时,无法建立连接。在浏览器 JS 控制台中,我收到 503 服务不可用消息。在heroku中,我得到了错误:
no primary found in replica set
我知道 Atlas MongoDB Cloud 需要 SSL 连接,这与 mLab 不同。在我的本地机器上,我想使用自签名证书成功连接到集群。
我的问题是:我是否需要在 Heroku 中获得 SSL 支持才能访问在 Heroku 和 MongoDB Atlas 之间建立安全连接?或者 Heroku 中的 SSL 支持只需要客户端/Heroku 安全连接?
【问题讨论】:
【参考方案1】:登录到云 MongoDB 站点并进入网络访问点击添加 IP 地址并点击允许从任何地方访问都可以工作
【讨论】:
这并没有在已经提出的建议中添加任何内容。【参考方案2】:由于允许从任何地方进行访问并不安全,而且 IP 范围可能会改变,我最终安装了附加组件 QuotaGuard Static IP's
(它为 IP 白名单提供了 2 个 IP 地址)所以 SOCKS5 Proxy can be used with QGTunnel。
QGTunnel 应该被下载并包含在代码库中
curl https://s3.amazonaws.com/quotaguard/qgtunnel-latest.tar.gz | tar xz
Procfile 应该更新
web: bin/qgtunnel npm start
假设您想使用 QGTunnel 访问一个复制的 MongoDB 集群,其中 3 个副本位于主机上:rs01.mongodb.net:52115
、rs02.mongodb.net:52115
和 rs1.mongodb.net:52115
。对于此配置,您需要在transparent mode 的端口 52115 上为每个主机创建 3 个单独的隧道。完成此操作后,QGTunnel 将更改 DNS 解析过程以将这些主机名解析为适当的环回地址,并且复制集群的自动发现应该按预期工作。
【讨论】:
【参考方案3】:您可以使用以下命令找到 Heroku 的所有 IP 范围:
HEROKU_REGION=eu; sudo apt -qqy install curl jq 2>/dev/null 1>/dev/null; heroku regions --json 2>/dev/null | jq ".[] | select(.name==\"$HEROKU_REGION\") | .provider.region" | (REGION=$(cat); curl -s https://ip-ranges.amazonaws.com/ip-ranges.json | jq ".prefixes[] | select(.region==$REGION) | .ip_prefix")
【讨论】:
惊人的答案。如果有人想手动执行此操作,因为他没有 apt - 找出您的 heroku 区域然后转到 ip-ranges.amazonaws.com/ip-ranges.json 并找到该区域的 IP 范围【参考方案4】:还必须将 0.0.0.0/0 添加到 Mongo IP 白名单并在 Heroku 上重新部署我的应用程序才能最终运行(在更改 IP 之前,引发了 CORS 错误)。
【讨论】:
【参考方案5】:非常简单的解决方案!只需将地址“0.0.0.0/0”添加到mongo atlas的白名单IP中
它将向全世界开放 mongo 地图集.....所以它不用于生产,但它有助于小型测试
【讨论】:
【参考方案6】:我认为可能会解决您的问题
免责声明:我没有使用过 Heroku 和 MongoDB Atlas,但我正在研究它们。
根据to a Github issue I found,如果您尚未将 MongoDB Atlas 中的服务器 IP 地址列入白名单,您将收到该错误消息。
阅读MongoDB Atlas docs,我看到与 Heroku dynos 结合使用的唯一方法是将0.0.0.0/0
(即所有地址)添加到您的 MongoDB Atlas 白名单中。
试一试,请报告您是否可以实例化连接。
在 SSL 上
尝试回答 SSL 问题,根据我阅读的内容,我认为您不需要在 Heroku 上启用它,尽管我不完全确定。
如果 MongoDB 服务器执行证书验证,则用于连接到它的 Node.js 代码必须如下所示(取自 Node.js driver documentation):
var MongoClient = require('mongodb').MongoClient,
f = require('util').format,
fs = require('fs');
// Read the certificates
var ca = [fs.readFileSync(__dirname + "/ssl/ca.pem")];
var cert = fs.readFileSync(__dirname + "/ssl/client.pem");
var key = fs.readFileSync(__dirname + "/ssl/client.pem");
// Connect validating the returned certificates from the server
MongoClient.connect("mongodb://localhost:27017/test?ssl=true",
server:
sslValidate:true
, sslCA:ca
, sslKey:key
, sslCert:cert
, sslPass:'10gen'
, function(err, db)
db.close();
);
如果 MongoDB 服务器不检查任何 SSL 证书,您可以简单地使用如下代码(也取自 Node.js driver documentation):
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/test?ssl=true", function(err, db)
db.close();
);
鉴于Atlas documentation 包含以下用于从 Node.js 连接到它的示例代码,我认为您确实不必在 Heroku 上启用 SSL:
var MongoClient = require('mongodb').MongoClient;
var uri = "mongodb://kay:myRealPassword@mycluster0-shard-00-00-wpeiv.mongodb.net:27017,mycluster0-shard-00-01-wpeiv.mongodb.net:27017,mycluster0-shard-00-02-wpeiv.mongodb.net:27017/admin?ssl=true&replicaSet=Mycluster0-shard-0&authSource=admin";
MongoClient.connect(uri, function(err, db)
db.close();
);
【讨论】:
尼克拉斯,你是对的!问题出在白名单访问中。关于 SSL 问题,我想你是对的,因为我得到 Herkou 支持的以下回复:“(...) 为应用程序使用 SSL 与 mongo 连接完全分开,所以我认为这不会是问题在这里。” 更新 (source): 由于 Heroku dynos 使用 AWS EC2 实例 IP 范围的子集,因此可以将 AWS IP ranges 添加到 Cloud Atlas 的白名单中,或获取附加组件以提供静态出站 IP 地址,或通过 TLS 使用安全通信。 太棒了!谢谢你的报告,布鲁诺。 :)【参考方案7】:我通过为数据库请求和其他 TCP 连接的静态 IP 地址安装插件(我使用 Fixie Socks)解决了这个问题。 更多选项在这里:https://elements.heroku.com/addons#network
【讨论】:
感谢分享,看来很有用。免费套餐是每月 100 个请求 100MB,听起来很低,什么算作“请求”? 你能分享一些关于你是如何做到这一点的代码吗?我试图了解我需要在我的 node.js express 代码中更改什么,以便使用 fixie socks 并通过 mongoose 进行连接。 也很想看到这个。我今天早些时候也给 Fixie Socks 发了电子邮件。 我研究过使用 Fixie Socks,但它只适用于美国地区 固定袜子有用吗?我正在尝试完全相同的设置,但每次都失败。以上是关于将 Heroku App 连接到 Atlas MongoDB 云服务的主要内容,如果未能解决你的问题,请参考以下文章
Heroku部署后Django(djongo)无法连接到MondoDB Atlas
尝试将 Heroku 连接到 Atlas MongoDB 时出现问题