36

FIXED (edited code to reflect changes I made)

I'm trying to connect to a Mongo database through an SSH tunnel using Java.

I'm using the Mongo driver 3.0.2 and jcraft (JSch) to create an SSH tunnel. The idea is that I:

  • connect to the machine hosting the MongoDB installation through SSH
  • set up port forwarding from a local port to the remote MongoDB port
  • connect to MongoDB remotely

My code looks like this:

// forwarding ports
private static final String LOCAL_HOST = "localhost";
private static final String REMOTE_HOST = "127.0.0.1";
private static final Integer LOCAL_PORT = 8988;
private static final Integer REMOTE_PORT = 27017; // Default mongodb port

// ssh connection info
private static final String SSH_USER = "<username>";
private static final String SSH_PASSWORD = "<password>";
private static final String SSH_HOST = "<remote host>";
private static final Integer SSH_PORT = 22;

private static Session sshSession;

public static void main(String[] args) {
try {
    java.util.Properties config = new java.util.Properties();
    config.put("StrictHostKeyChecking", "no");
    JSch jsch = new JSch();
    sshSession = null;
    sshSession = jsch.getSession(SSH_USER, SSH_HOST, SSH_PORT);
    sshSession.setPassword(SSH_PASSWORD);
    sshSession.setConfig(config);
    sshSession.connect();
    sshSession.setPortForwardingL(LOCAL_PORT, REMOTE_HOST, REMOTE_PORT);

    MongoClient mongoClient = new MongoClient(LOCAL_HOST, LOCAL_PORT);
    mongoClient.setReadPreference(ReadPreference.nearest());
    MongoCursor<String> dbNames = mongoClient.listDatabaseNames().iterator();
    while (dbNames.hasNext()) {
    System.out.println(dbNames.next());
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    sshSession.delPortForwardingL(LOCAL_PORT);
    sshSession.disconnect();
}
}

This code, when run, doesn't EDIT: does work. Connecting to the SSH server works just fine, but connecting to the Mongo database behind it doesn't work and returns this error:

INFO: Exception in monitor thread while connecting to server localhost:8988
com.mongodb.MongoSocketReadException: Prematurely reached end of stream
    at com.mongodb.connection.SocketStream.read(SocketStream.java:88)
    at com.mongodb.connection.InternalStreamConnection.receiveResponseBuffers(InternalStreamConnection.java:491)
    at com.mongodb.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:221)
    at com.mongodb.connection.CommandHelper.receiveReply(CommandHelper.java:134)
    at com.mongodb.connection.CommandHelper.receiveCommandResult(CommandHelper.java:121)
    at com.mongodb.connection.CommandHelper.executeCommand(CommandHelper.java:32)
    at com.mongodb.connection.InternalStreamConnectionInitializer.initializeConnectionDescription(InternalStreamConnectionInitializer.java:83)
    at com.mongodb.connection.InternalStreamConnectionInitializer.initialize(InternalStreamConnectionInitializer.java:43)
    at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:115)
    at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:127)
    at java.lang.Thread.run(Unknown Source)

I've tried doing this through command line as follows:

$ ssh <user>@<host> -p 22 -X -C
$ <enter requested password>
<user>@<host>$ mongo
<user>@<host>$ MongoDB shell version: 2.6.10
<user>@<host>$ connecting to: test

So this seems to work. I'm at a loss as to why the Java code (which should be doing roughly the same thing) doesn't work.

David V
  • 360
  • 3
  • 6
  • 2
    Is mongo running on the SSH server host? Could you run "netstat -an | grep 27071" on the SSH server host and edit your question to include the output? I'd like to see exactly how mongo is listening for connections. – Kenster Jul 01 '15 at 13:54
  • 1
    I managed to make it work (tried to forward port to "localhost" rather than "127.0.0.1", changing it fixed it) edit: I guess the server was listening specifically on localhost rather than 127.0.0.1, so I think that also answers your question Kenster. – David V Jul 01 '15 at 14:12
  • I know thank yous are usually not needed, but man, my head was starting to hurt. This solved my issue I've been trying to figure what was wrong for the past day! – StanM Jul 22 '15 at 20:12
  • 2
    You generally shouldn't use all capitals for variables that aren't constants. SSH_SESSION isn't a constant, you mutate it. Glad you got it working, though – Carson Graham Dec 10 '19 at 18:56
  • 7
    @DavidV You should revert the question to what it used to be, and post the solution as an answer. – OrangeDog Oct 28 '20 at 12:42
  • 4
    @DavidV answer your own question and accept it so this one stops popping up on my unanswered searches :) – Alexandre Juma Nov 30 '20 at 14:38
  • 1
    localhost might resolve to an IPv6 address, whereas 127.0.0.1 is IPv4. I'm guessing MongoDB server does not support dual-stack, or is configured specifically to use IPv4 ? – blagerweij Jan 01 '21 at 23:40
  • You may run the ssh in another thread or a seperate application/process, then set the java proxy in the mongoDB connection. – meadlai Jun 15 '21 at 04:06

2 Answers2

0

I managed to make it work (tried to forward port to "localhost" rather than "127.0.0.1", changing it fixed it) edit: I guess the server was listening specifically on localhost rather than 127.0.0.1

David V
  • 360
  • 3
  • 6
-2

This code is run successfully, but the main problem is your mongo db is stopped. Please check the instance of the mongo is running or not.

sudo systemctl status mongod

if it is not running

sudo systemctl start mongod
mcolak
  • 609
  • 1
  • 7
  • 13