I’m having trouble connecting to my MongoDB (6.0.6) instance, which is running on an EC2 machine with TLS, through an SSH Tunnel in TypeScript. Previously, I was able to establish the connection successfully using Python. However, when I try to establish the same connection using ssh2 and mongoose in TypeScript, it fails. Can anyone provide guidance or a solution to resolve this issue?
The Python code that works:
from sshtunnel import SSHTunnelForwarder
from pymongo import MongoClient
# VM IP/DNS - Will depend on your VM
EC2_URL = '''<ec2 address>'''
# Mongo URI Will depende on your DocDB instances
DB_URI = '''<DB address>'''
# DB user and password
DB_USER = '<user>'
DB_PASS = '<pass'
# Create the tunnel
server = SSHTunnelForwarder(
(EC2_URL, 22),
ssh_username='<ec2 username>',
ssh_pkey='AWS_User_Keys.pem',
remote_bind_address=(DB_URI, 27017)
)
# Start the tunnel
server.start()
server.check_tunnels()
print(server.local_bind_port)
# Connect to Database
client = MongoClient(
host='localhost',
port=server.local_bind_port,
username=DB_USER,
password=DB_PASS,
tls=True,
tlsCAFile='AWS_DocDB_Auth.pem',
retryWrites=False,
directConnection=True,
tlsAllowInvalidHostnames=True
)
print("list is:")
print(client.list_database_names())
# Close the tunnel once you are done
server.stop()
The TypeScript code that doesnt:
import { Client, ConnectConfig } from 'ssh2';
import * as mongoose from 'mongoose';
import * as fs from 'fs';
const localPort = 3000; // Local port to listen on
const remoteHost = '<ec2 address>'; // Remote MongoDB server
const remotePort = 27017; // Remote MongoDB port
const privateKeyPath = './AWS_User_Keys.pem'; // Path to your private key
const sshConfig: ConnectConfig = {
host: '<ec2 address>', // SSH server
port: 22, // SSH port
username: '<ec2 username>', // SSH username
privateKey: fs.readFileSync(privateKeyPath), // Read the private key from file
};
const startSshTunnel = async (): Promise<Client> => {
return new Promise((resolve, reject) => {
const conn = new Client();
conn.on('ready', () => {
conn.forwardOut(
'localhost',
localPort,
remoteHost,
remotePort,
(err, stream) => {
if (err) {
reject(err);
}
resolve(conn);
}
);
});
conn.connect(sshConfig);
});
};
startSshTunnel()
.then((sshClient) => {
console.log('SSH tunnel started');
// Set up Mongoose connection using the SSH tunnel with username and password
mongoose.connect(`mongodb://<ec2 address>:27017/<DB name>`, {
auth: {
username: '<user>>',
password: '<pass>',
},
tls: true,
tlsCAFile: './Mongo_server_certificate_key.pem', // Path to the CA certificate file
});
// Perform Mongoose operations as needed
const db = mongoose.connection;
db.collection('test').insertOne({ name: 'John Doe' });
db.once('open', () => {
console.log('Connected to MongoDB via SSH tunnel with TLS');
db.collection('test').insertOne({ name: 'John Doe' });
});
db.on('error', console.error.bind(console, 'MongoDB connection error:'));
})
.catch((error) => {
console.error('Error starting SSH tunnel:', error);
});
The error message:
....TS_SSH_Test\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:185
const err = new MongooseError(message);
^
MongooseError: Operation `test.insertOne()` buffering timed out after 10000ms
at Timeout.<anonymous> (....TS_SSH_Test\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:185:23)
at listOnTimeout (node:internal/timers:559:17)
at processTimers (node:internal/timers:502:7)