【问题标题】:Connecting Heroku App to Atlas MongoDB Cloud service将 Heroku App 连接到 Atlas MongoDB 云服务
【发布时间】:2017-06-28 18:56:40
【问题描述】:

预测问题:我是否需要在 Heroku 上获得 SSL 支持才能在 HerokuAtlas 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 安全连接?

【问题讨论】:

    标签: node.js mongodb ssl heroku mongoose


    【解决方案1】:

    我认为可能会解决您的问题

    免责声明:我没有使用过 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 使用安全通信。
    • 太棒了!谢谢你的报告,布鲁诺。 :)
    【解决方案2】:

    我通过为数据库请求和其他 TCP 连接的静态 IP 地址安装插件(我使用 Fixie Socks)解决了这个问题。 更多选项在这里:https://elements.heroku.com/addons#network

    【讨论】:

    • 感谢分享,看来很有用。免费套餐是每月 100 个请求 100MB,听起来很低,什么算作“请求”?
    • 你能分享一些关于你是如何做到这一点的代码吗?我试图了解我需要在我的 node.js express 代码中更改什么,以便使用 fixie socks 并通过 mongoose 进行连接。
    • 也很想看到这个。我今天早些时候也给 Fixie Socks 发了电子邮件。
    • 我研究过使用 Fixie Socks,但它只适用于美国地区
    • 固定袜子有用吗?我正在尝试完全相同的设置,但每次都失败。
    【解决方案3】:

    非常简单的解决方案!只需将地址“0.0.0.0/0”添加到mongo atlas的白名单IP中

    它将向全世界开放 mongo 地图集.....所以它不用于生产,但它有助于小型测试

    【讨论】:

      【解决方案4】:

      还必须将 0.0.0.0/0 添加到 Mongo IP 白名单并在 Heroku 上重新部署我的应用程序才能最终运行(在更改 IP 之前,引发了 CORS 错误)。

      【讨论】:

        【解决方案5】:

        您可以使用以下命令找到 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 范围
        【解决方案6】:

        由于允许从任何地方进行访问并不安全,而且 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:52115rs02.mongodb.net:52115rs1.mongodb.net:52115。对于此配置,您需要在transparent mode 的端口 52115 上为每个主机创建 3 个单独的隧道。完成此操作后,QGTunnel 将更改 DNS 解析过程以将这些主机名解析为适当的环回地址,并且复制集群的自动发现应该按预期工作。

        【讨论】:

          【解决方案7】:

          登录到云 MongoDB 站点并进入网络访问点击添加 IP 地址并点击允许从任何地方访问都可以工作

          【讨论】:

          • 这并没有对已经提出的建议添加任何内容。
          猜你喜欢
          • 2021-04-05
          • 2020-10-07
          • 1970-01-01
          • 1970-01-01
          • 2019-01-27
          • 2018-09-28
          • 1970-01-01
          相关资源
          最近更新 更多