How To Read From Apache SSHD Forwarded Port

21 Views Asked by At

I am attempting to use Apache SSHD to start local port forwarding and then read data from the local port in Java.

I can do this without Apache SSHD by using OpenSSH to start local port forwarding and then just create and read from a Socket in Java. This works as expected.

When I try to replicate this with Apache SSHD instead of using OpenSSH, I get no errors but cannot read from the Socket. Why can't I read from the Socket in the same way I can when using OpenSSH? Am I missing something with Apache SSHD?

Example using OpenSSH:

ssh -i keyfile -l username -L 12345:127.0.0.1:20130 sshServerAddress

Then leave that connection open and run some simple Socket reading code in Java:

Socket socket = new Socket("127.0.0.1", 12345);
socket.setSoTimeout(0);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new BUfferedInputStream(socket.getInputStream())))) {
  String line = reader.readLine();
  System.out.println(line);
}

When I do this, it prints the expected data being delivered over the tunnel.

I then tried to replicate this in Apache SSHD, and the connection completed without error, but when I try to read from the socket, it just returns null. Does anyone have any clues as to what is missing?

SshClient sshClient = SshClient.setUpDefaultClient();
sshClient.setForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
sshClient.start();

ClientSession session = sshClient.connect(username, sshServerAddress, 22).verify(10000, TimeUnit.MILLISECONDS).getSession();
FileKeyPairProvider keyPairProvider = new FileKeyPairProvider(keyfile.toPath());
keyPairProvider.setPasswordFinder(FilePasswordProvider.of(passphrase));
clientSession.setKeyIdentityProvider(keyPairProvider);
clientSession.setUsername(username); // is this redundant?
clientSession.auth().verify(10000, TimeUnit.MILLISECONDS);

SshdSocketAddress sshdSocketAddress = clientSession.startLocalPortForwarding(12345, new SshdSocketAddress("127.0.0.1", 20130));

Socket socket = new Socket("127.0.0.1", 12345);
socket.setSoTimeout(0);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new BUfferedInputStream(socket.getInputStream())))) {
  String line = reader.readLine();
  System.out.println(line);
}

So Apache SSHD didn't throw any errors. It authenticated and executed the port forwarding code. But why can't I then read from the local port?

For reference, I ran this test using org.apache.sshd sshd-core and sshd-common artifacts version 2.7.0.

UPDATE: I discovered that if I also open a shell channel, I can see the same output I would see if I were instead starting the port forwarding with OpenSSH, and I can also then read data on the forwarded port. But I still need to determine how to set this up properly. Example (I put this code prior to starting local port forwarding):

ChannelShell cshell = clientSession.createShellChannel();
cshell.setOut(new NoCloseOutputStream(System.out));
cshell.setErr(new NoCloseOutputStream(System.err));
cshell.open().verify(10000, TimeUnit.MILLISECONDS);

It's possible the server wouldn't actually fully initialize until I had accepted it's output. Now I need to figure out how to implement this in a proper way. I don't really care about the shell, I really just want to ignore it and consume data from the local port that port forwarding was set up for.

0

There are 0 best solutions below