如何在 Nginx 反向代理后面设置 MongoDB

Posted

技术标签:

【中文标题】如何在 Nginx 反向代理后面设置 MongoDB【英文标题】:How to setup MongoDB behind Nginx Reverse Proxy 【发布时间】:2015-10-29 11:35:58 【问题描述】:

我正在尝试将 nginx 设置为访问 MongoDB 数据库的反向代理。默认情况下,Mongo 监听 27017 端口。我想要做的是通过 nginx 重定向主机名,例如 mongodb.mysite.com 并将其传递给 mongodb 服务器。这样,我将从外部网络关闭我已知的 27017 端口,并像我给出的示例一样从隐藏的 url 访问我的数据库。

所以我正在尝试使用此配置设置 Nginx:

server 
        listen 80;
        server_name mongo.mysite.com;
        gzip off;       

        location / 
            proxy_pass http://127.0.0.1:27017;
            proxy_redirect off;
            proxy_buffering off;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
        
    

因此,在完成此操作后,我尝试使用命令 mongo mongo.mysite.com:80 从我的 cmd 与 mongo shell 连接,我得到以下错误:

2015-08-06T13:44:32.670+0300 I NETWORK  recv(): message len 1347703880 is invalid. Min 16 Max: 48000000
2015-08-06T13:44:32.670+0300 I NETWORK  DBClientCursor::init call() failed
2015-08-06T13:44:32.674+0300 E QUERY    Error: DBClientBase::findN: transport error: mongo.therminate.com:80 ns: admin.$cmd query:  whatsmyuri: 1 
    at connect (src/mongo/shell/mongo.js:181:14)
    at (connect):1:6 at src/mongo/shell/mongo.js:181
exception: connect failed

在 Nginx 访问日志中我也得到了这个:

94.66.184.128 - - [06/Aug/2015:10:44:32 +0000] "<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xD4\x07\x00\x00\x00\x00\x00\x00admin.$cmd\x00\x00\x00\x00\x00\x01\x00\x00\x00\x15\x00\x00\x00\x10whatsmyuri\x00\x01\x00\x00\x00\x00" 400 172 "-" "-"

有没有人知道,这里出了什么问题?谢谢!

【问题讨论】:

【参考方案1】:

加上@Néstor 的回答,这个配置应该写到/etc/nginx.conf 上面http 部分,像这样:

stream 
    server 
        listen  <your incoming Mongo TCP port>;
        proxy_connect_timeout 1s;
        proxy_timeout 3s;
        proxy_pass    stream_mongo_backend;
    

    upstream stream_mongo_backend 
        server <localhost:your local Mongo TCP port>;
    


http 
    ...

您应该绝不将其写入.conf 文件,然后将文件放入/etc/nginx/sites-available 文件夹。因为/etc/nginx/sites-available 文件夹中的任何配置信息都属于http 部分。

【讨论】:

非常感谢您,但是如何指定 server_name ?我有多个 dns 记录指向不同站点的 nginx 等,我想将 mongodb 流指向特定域名。 @AdamD 在我的示例中,我将 server_name 设置为 localhost,您可以将 localhost 更改为您的域。 @AdamD 你是如何设法添加域的? 嗨@Kingname,有没有试过用于mongodb副本集的nginx代理?我试图添加我的服务器,但远程我无法连接到副本集,只能连接到单个主机。 你好,写完之后,我还要在/sites-available中写路由吗?【参考方案2】:

你是对的,你需要通过在你的 .conf 文件中添加一个流部分来使用 NGINX 的流模块:

stream 
    server 
        listen  <your incoming Mongo TCP port>;
        proxy_connect_timeout 1s;
        proxy_timeout 3s;
        proxy_pass    stream_mongo_backend;
    

    upstream stream_mongo_backend 
      server <localhost:your local Mongo TCP port>;
  

【讨论】:

我可以将其配置为 mongo.example.co'? If so, how do I specify the address? I tried server_name` 并且它抱怨指令不允许 @KhoPhi 您是如何添加域的? @KhoPhi 您是否曾经设法将其限制为单个域?我找不到任何关于这样做的文档,但它一定是可能的。 @Chrift 我不记得让它工作了。我想我放弃了那个领域。我通过后端使用通常的 API 方法来访问数据库【参考方案3】:

我把这个抛在了脑后,但做了一些工作后,我不得不再次面对这个问题,这一次我想到了解决方案!

NGINX 基本上是一个 HTTP 服务器,因此通过上述方式设置重定向和代理,它将所有通信包装在 HTTP 协议中。所以正在发生的错误是,当 Mongo 期待原始 TCP 流量时,它正在获取 HTTP 流量。

所以解决这个问题的方法是使用 NGINX 的新 stream module 来处理原始 TCP 流量,并将上游服务器设置为指向 mongodb 实例。

更多信息:NGINX stream module

【讨论】:

嗨@mitsos1os,你能这么温柔地放一些代码示例吗?很高兴看到您是如何做到的,因为文档没有讨论如何将域名映射到服务器。任何帮助都会有很大帮助:D 你好@mitsos1os,你能详细说明你的答案吗?我面临着完全相同的问题,但是当我使用流模块时,我无法使用默认端口,我不得不使用 http 接口使其工作,这并不理想。 嗨@mitsos1os,您如何将身份验证参数从Nginx 传递到Mongo?在 SCRAM 和 X.509 的情况下? @Viraj 我不是 100% 确定,但我相信,由于您直接将 TCP 连接从 Nginx 传递到 Mongo,它将能够处理您想要的任何身份验证机制。查看 Nestor 和 Kingname 的其余示例【参考方案4】:

如果您通过通常的默认 ip 值连接到本地 mongodb 实例,它应该连接:mongo 10.8.8.10

问题在于通过没有发生的 mongodb shell 解析地址。

【讨论】:

我真的听不懂你说什么。该地址已正确解析,因为在 nginx 日志中我可以看到它正在记录访问数据库的尝试,因此解析了主机名。此外,如果我直接打开 27017 端口并尝试使用主机名连接并跳过 nginx,它可以正常工作。所以这不是地址解析的问题 对不起,如果我不清楚。在我编辑我的帖子之前,我想到了另外两件事。 [1] 您能否重新启动 mongod 并重新连接以查看此问题是否可重现 [2] 如果您已经完成了第 1 步,那么您的 mongod 会显示什么......它是否显示您在上面发布的失败尝试。 ..?编辑:[3] tail -f /var/log/mongodb/mongodb.log 应该告诉你更多

以上是关于如何在 Nginx 反向代理后面设置 MongoDB的主要内容,如果未能解决你的问题,请参考以下文章

nginx 反向代理 虚拟二级目录

如何在带有 SSL 的 nginx 反向代理后面正确运行 BeEF

在带有协议升级的 nginx 反向代理后面运行 daphne 总是路由到 http 而不是 websocket

nginx反向代理-后端服务器组设置

设置好 NGINX 反向代理后,如何在引入 NGINX 反向代理的 NGINX 上配置 SSL 直通? [复制]

keycloak 无效参数:redirect_uri 在反向代理后面