Using SSH connection for inter application communication
Asked Answered
C

2

3

I want to write an application that would be a custom SSH server with two types of connection:

  • A sync channel, where clients type a command and the server would return the output
  • An stream channel where the user connects and starts reading the IO, the server publishes data continuously.

I am doing that in Java, I think Apache Mina SSHD in the right tool for that. I managed to write some code for authentication (thanks to resources found on the net) and could run the /bin/sh on my connection so I am all setup I guess. The problem is that from now I am stuck, due to lack of knowledge on how these things works and how Mina works specifically.

Basically I would need to have access to the input and output stream for each SSH connection, after that I can sort out things on my own, buy what's the right way to get that?

Should I make a custom Channel ? A custom Shell ? A custom set of commands ?

Could any one point me to resources on the subject ?

Chuffy answered 5/10, 2012 at 11:41 Comment(4)
This doesn't exactly answer your question, but I would approach this differently. I would separate the SSH connections from your application. Have you thought about opening a port for each of the two channels you talk about, then if clients can't access those ports directly, you can have them tunnel those ports over an ssh connection using the '-L' flag in the ssh connection command?Octan
@bohney: +1. Simpler, easier to setup and maintain.Dissymmetry
Not sure i understand, but I am basically writing a mock for a third party service we use, so I am a bit limited on architectural options. Also I am integrating this within an Akka application (in scala)Chuffy
The client side is already written actually, using an SSH library.Chuffy
C
2

I have found the solution:

First you have to implement a Command factory, which is done as follow:

class CommandFactory extends Factory[Command] {

  override def create():Command = {
    new Command() {
      def destroy() {}

      def setInputStream(in: InputStream) {}

      def setErrorStream(err: OutputStream) {}

      def setOutputStream(out: OutputStream) {}

      def start(env: Environment) {}

      def setExitCallback(callback: ExitCallback) {}
    }
  }
}

Then you set up your ssh server like that:

sshd.setShellFactory(new CommandFactory())

Of course you can extend the implementation to pass anything you need to the command.

The implementation of the command is where you define the behaviour of your shell.

Chuffy answered 9/10, 2012 at 13:23 Comment(1)
"Of course you can extend the implementation to pass anything you need to the command." How do I achieve this.... I need to implement my own costume command. I was successfully updated my code till creating a Command class with start and other implemented methods.... my doubt is how I can capture the commands entered in the ssh connection and compare if it is my customer command or not and if it is , do the necessary action ... Please need this help urgentlyRationality
O
0

This is a follow-up to my comment posted to the question itself.

To allow a client (client) to access ports on a remote machine (server) directly or through another computer on the same network as the server (gateway) through SSH, you just have to use the -L flag.

From client to server directly (port 8080 on the client's machine will tunnel to 80 on the server):

ssh -L 8080:localhost:80 server

From client to server through a gateway (port 8080 on the client's machine will tunnel to 80 on the server):

ssh -L 8080:server:80 gateway

From the man pages for ssh, here is how you use the -L flag:

     -L [bind_address:]port:host:hostport
         Specifies that the given port on the local (client) host is to be
         forwarded to the given host and port on the remote side.  This
         works by allocating a socket to listen to port on the local side,
         optionally bound to the specified bind_address.  Whenever a
         connection is made to this port, the connection is forwarded over
         the secure channel, and a connection is made to host port
         hostport from the remote machine.  Port forwardings can also be
         specified in the configuration file.  IPv6 addresses can be
         specified by enclosing the address in square brackets.  Only the
         superuser can forward privileged ports.  By default, the local
         port is bound in accordance with the GatewayPorts setting.
         However, an explicit bind_address may be used to bind the
         connection to a specific address.  The bind_address of
         ``localhost'' indicates that the listening port be bound for
         local use only, while an empty address or `*' indicates that the
         port should be available from all interfaces.
Octan answered 5/10, 2012 at 13:34 Comment(1)
Thanks, but that does not answer my question: I need to have access to the input and output streams as java buffers so that I can program my own commands and output stream. The idea for me on the server side would be to read the input, interpret that as a command, process and write the answer on the output. For the stream version, I would not read the input, just publish my data on the outputChuffy

© 2022 - 2024 — McMap. All rights reserved.