Before we propose a solution, I need to make sure that our assumptions are correct:
- I assume that any solutions that require any configuration changes at the 'firewall' are not acceptable. Is that correct?
- On the other hand, I assume it is possible to install and run a custom .NET application (possibly based on Rebex libraries) on the 'proxy server'. Please confirm whether this is the case.
- If both of the assumptions are correct, any solution would involve setting up a different kind of proxy server (possibly an SSH server) outside the 'firewall' to facilitate the communication. Is that acceptable as well?

At the proxy server, run an application that uses Rebex Terminal Emulation's port forwarding API to establish an incoming tunnel (or a set of tunnels) from an address/port at the external SSH server to a machine behind the firewall.

Details:

(1) Any SSH server that supports reverse port forwarding is suitable. An OpenSSH server on a Linux VPS would be fine. (Our Buru SFTP Server is intended for file transfer and doesn't support reverse port forwarding yet.)

With this setup, an application outside the firewall would be able to connect to (for example) sshserver.example.org:11022 and the connection would get tunneled to 192.168.1.2:22.

With this approach, all of the possible tunnels would have to be pre-configured. Or, in other words, the application outside the firewall could not connect to any IP/port behind the firewall. This could be both a drawback or a benefit, depending on your scenario. But if you need the ability for the application to connect to any IP/port behind the firewall, this could be achieved by first connecting to an SSH server behind the firewall and using forward port forwarding to reach the other machines.

So, I come up with some news. After a lot of prototyping, I managed to implement the desired behavior using the FileServer, but only to the point that I can establish a "duplex" communication channel between the SSH server and the Proxy server. How I did it?

1. The Proxy server initiates the connection by creating two SSH sessions (Ssh component): one for the input queue and the other one for the output queue.

2. The SSH Server receives the commands in the ShellCommand event from the Proxy. The session of the Proxy's input queue becomes the session of the SSH Server's output queue (ServerSession component) and the session of the Proxy's output queue becomes the session of the SSH Server's input queue (also ServerSession component).

Side note: at this point it would be interesting to see how can I use a sigle session for the duplex communication (currently, when I use a single session for the input and output queues, a Send would crash if a ReadLine is active).

The communication works fine so far. The problem arises when I try to start a tunnel from the SSH Server to a target. So here is the flow, assuming that the duplex connection is up and running:

1. Identify a free port on the SSH Server.
2. Send to the proxy the free port number and the target host/port.
3. The proxy uses its out queue's SSH session to start an incoming tunnel from (127.0.0.1, free-port) to (target-host, target-port). BANG! This is the moment when the method crashes with the cryptical "The request has failed" exception.
(from log: ID:3|area:SSH|Rebex.Net.SshException: The request has failed.
at Rebex.Net.SshSession.ExecuteRequest(ConnectGlobalRequest request, GlobalRequestKind kind)
at Rebex.Net.SshSession.StartTcpIpForward(String address, Int32 port))

This is the region which generates the crash:
object[] result = WaitFor<object[], SshGlobalRequest>(ExecuteRequestFinishCheck, r);
if (result == null)
throw new SshException(SshExceptionStatus.OperationFailure, SshStrings.RequestFailed);

Trying to build a tunnel using putty indicates an error: "Remote port forwarding from 127.0.0.1:4800 refused." (a connection was previously established to the server, and the tunnel is created in this connection.)

Side note: there is no notification in both Ssh and ServerSession when the underlying connection is closed/dead (such as a Closed event). I implemented a timer that checks periodically (each minute) if the connection is alive.

It looks like you choose to implement this in a different way using a lower level API, but at quick glance it looks like it should work as well. However, as I already mentioned on May 6th, Rebex File Server does not support incoming SSH tunneling yet, and that means it will reject all SshSession.StartTcpIpForward requests.

This is actually one of the features we would like to add soon, but we are currently busy with other features and this is not in our near-term plans yet. At this point, our recommendation would be to use a different SSH server, but that approach is not compatible with your solution.

However, the list of customers who would like this feature keeps growing, so we will consider reprioritizing this. What is your project's schedule? Would a beta with incoming SSH tunnel support be sufficient for a month or two?