Cannot connect to MongoDB when tunneling SSH connection

Question:

I am developing a GUI using Flask. I am running Ubuntu 20.04. The data that I need is from MongoDB, which is running on a Docker container on a server. My Mongo URI is "mongodb://<USERNAME>:<PASSWORD>@localhost:9999/<DB>?authSource=<AUTHDB>".

First I tunnel the SSH connection to the server:

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

When I connect to a Mongo shell after tunneling the connection, it works as expected. The issue is when I try to run the Flask app. PyMongo cannot seem to connect to the database (connection refused).

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')>]>

Another error I’ve been seeing is PyMongo authentication failed. This only happens if I have a Docker container with Mongo running on my local machine. (The previous error only happens when the local container is not running).

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'x16x8cx11xb2Ufxe3x80x85xb0 >xcbxbexa5Sx8fxec(g', 'keyId': 7128054189753630722}}, 'operationTime': Timestamp(1660576452, 1)}

One last thing: I have not experienced any errors when trying to connect to the local MongoDB running in a local Docker container. This leads me to believe that I am missing a step when connecting to the remote MongoDB. And it’s not a problem with the URI since I can log into a Mongo shell with it when the SSH connection is up.

Here is some code from my Flask app:

init.py

from flask import Flask
from flask_bootstrap import Bootstrap
from .frontend import frontend
from .database import mongo

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

Does anyone know why I am getting these errors? Thanks.

Asked By: strK

||

Answers:

I discovered that pymongo isn’t setting the port correctly, possibly due to a bug in the package. Even though I specify the port as 9999, it thinks it should connect to 27017.

If I set the URI to "mongodb://<USERNAME>:<PASSWORD>@garbage:9999/<DB>?authSource=<AUTHDB>", then it will actually try to connect to port 9999.

I ended up changing my ssh tunnel to port 27017, and everything worked.

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

Answered By: strK