You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SSH隧道模式下Flask应用无法连接远程MongoDB求助

问题描述

我在Ubuntu 20.04上用Flask开发GUI,数据来自服务器Docker容器中的MongoDB。Mongo URI为:

mongodb://<USERNAME>:<PASSWORD>@localhost:9999/<DB>?authSource=<AUTHDB>

先通过以下命令建立到服务器的SSH隧道:

ssh -L 9999:localhost:27017 -N <USER>@<HOST>

建立隧道后,Mongo Shell能正常连接数据库,但运行Flask应用时PyMongo报错:

pymongo.errors.ServerSelectionTimeoutError: 127.0.0.1:9999: [Errno 111] Connection refused, Timeout: 30s, Topology Description: <TopologyDescription id: 62fa50c9015294b6e1df5811, topology_type: Unknown, servers: [<ServerDescription ('127.0.0.1', 9999) server_type: Unknown, rtt: None, error=AutoReconnect('127.0.0.1:9999: [Errno 111] Connection refused')>]>

另外,当本地运行Mongo Docker容器时,会出现PyMongo认证失败的错误:

pymongo.errors.OperationFailure: Authentication failed., full error: {'ok': 0.0, 'errmsg': 'Authentication failed.', 'code': 18, 'codeName': 'AuthenticationFailed', '$clusterTime': {'clusterTime': Timestamp(1660576452, 1), 'signature': {'hash': b'\x16\x8c\x11\xb2Uf\xe3\x80\x85\xb0 >\xcb\xbe\xa5S\x8f\xec(g', 'keyId': 7128054189753630722}}, 'operationTime': Timestamp(1660576452, 1)}

注:连接本地Docker部署的MongoDB无问题,SSH连接正常时Mongo Shell能登录,推测远程连接遗漏了步骤,URI本身无问题。

Flask相关代码:

init.py

from flask import Flask
from flask_bootstrap import Bootstrap
from .frontend import frontend
from .database import mongo
import os  # 补充原代码缺失的os导入

def create_app(configfile=None):
    app = Flask(__name__)
    app.config["MONGO_URI"] = "mongodb://<USERNAME>:<PASSWORD>@localhost:9999/<DB>?authSource=<AUTHDB>"

    Bootstrap(app)
    mongo.init_app(app)
    
    app.register_blueprint(frontend)
    app.secret_key = os.environ['SECRET_KEY']

    app.config['BOOTSTRAP_SERVER_LOCAL'] = True

    return app

database.py

from flask_pymongo import PyMongo

mongo = PyMongo()

frontend.py

from flask import Blueprint
from .database import mongo

frontend = Blueprint('frontend', __name__)

# Rest of file contains routes with calls to database
解决方案

问题1:SSH隧道下PyMongo连接拒绝

原因及修复步骤

  1. SSH隧道绑定地址限制
    默认ssh -L仅绑定127.0.0.1,若Flask应用尝试通过IPv6或主机名访问会失败。修改SSH命令绑定所有地址:
ssh -L 0.0.0.0:9999:localhost:27017 -N <USER>@<HOST>

同时将Mongo URI中的localhost改为127.0.0.1,避免解析到IPv6地址:

app.config["MONGO_URI"] = "mongodb://<USERNAME>:<PASSWORD>@127.0.0.1:9999/<DB>?authSource=<AUTHDB>"
  1. Flask容器网络隔离
    若Flask在Docker容器中运行,本地SSH隧道端口未映射到容器内。可选择两种方式:
  • 添加端口映射并使用容器主机别名:
    docker run -p 5000:5000 --add-host=host.docker.internal:host-gateway your-flask-image
    
    对应URI改为:
    app.config["MONGO_URI"] = "mongodb://<USERNAME>:<PASSWORD>@host.docker.internal:9999/<DB>?authSource=<AUTHDB>"
    
  • 使用主机网络模式:
    docker run --network=host your-flask-image
    
  1. 防火墙/SELinux限制
    检查本地防火墙是否允许127.0.0.1:9999的连接:
sudo ufw status

若有规则限制,添加允许规则:

sudo ufw allow in from 127.0.0.1 to 127.0.0.1 port 9999

若启用SELinux,临时关闭测试:

sudo setenforce 0

测试有效后再配置永久规则。

问题2:本地Mongo容器运行时认证失败

原因及修复步骤

  1. 本地与远程认证配置不一致
    本地Mongo容器可能使用了不同的authSource、用户名或密码。进入本地容器确认配置:
docker exec -it <mongo-container-name> mongosh
use <LOCAL-AUTHDB>
db.getUser("<LOCAL-USERNAME>")

建议用环境变量区分本地和远程配置,避免混用:

import os

if os.environ.get('ENV') == 'production':
    app.config["MONGO_URI"] = "mongodb://<REMOTE-USER>:<REMOTE-PASS>@127.0.0.1:9999/<REMOTE-DB>?authSource=<REMOTE-AUTHDB>"
else:
    app.config["MONGO_URI"] = "mongodb://<LOCAL-USER>:<LOCAL-PASS>@localhost:27017/<LOCAL-DB>?authSource=<LOCAL-AUTHDB>"
  1. 密码特殊字符未转义
    若密码包含@、:、/等特殊字符,需进行URL编码。用Python工具处理:
from urllib.parse import quote_plus

username = quote_plus("<USERNAME>")
password = quote_plus("<PASSWORD>")
app.config["MONGO_URI"] = f"mongodb://{username}:{password}@127.0.0.1:9999/<DB>?authSource=<AUTHDB>"

内容的提问来源于stack exchange,提问作者strK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 14:36:18