Hi Martin,

I just saw that the current api (in master branch) does not have callback for 
openning reverse tcpip forwarding channel.

Can you try the attached patch, add a callback for 
"channel_open_request_forwarded_tcpip_function" in client session callback 
struct.

We might ask for a pull request of this patch if it works better.


Regards,


Meng


________________________________
De : Martín Fernández <[email protected]>
Envoyé : lundi 16 avril 2018 22:35:23
À : Meng Hourk Tan; [email protected]
Objet : RE: Global Request for tcpip reverse forward


Meng,

Any change you can take a look at my last email ?

Thanks a lot!

Martín

On Fri, Mar 30, 2018 at 2:00 PM "Martín Fernández" <">"Martín Fernández" 
<mailto:> > wrote:
Meng,

Thanks again for the reply, seriously!

So, I have to admit that I get really confused with the semantics of 
remote_port between client and server. I know that in my example code the ports 
are probably wrong. Client is requesting port 2000 that is being used by my ssh 
server. When server receives request for port 2000 it just ignores it and 
replies with “I will use port 8080”. Then the reverse channel is opened on port 
8080. I’m not sure what are the semantics of this port when calling 
open_reverse really.

I added an event loop that same way I have on my server but in the client. 
Every time the poll returns a status is -2 (SSH_AGAIN) so I don’t understand 
why the client is not logging the `SSH_MSG_CHANNEL_OPEN` message from server. 
Maybe the open_reverse ports have something to do with this ? Not sure really.

Regarding the socket and binding, yes, I understand what you are saying. I’m 
completely responsible for opening socket and forwarding data when connection 
arrives. I first want to get the other part working. It should be possible to 
open the channel on the server and send information to the client simulating 
that a connection arrived in the server. That is what I’m trying to achieve 
first!

Thanks a lot for all the help!

Martín

On Fri, Mar 30, 2018 at 7:06 AM Meng Hourk Tan <Meng Hourk Tan 
<mailto:Meng%20Hourk%20Tan%20<[email protected]>> > wrote:

Hi Martin,


First, your port requested in the global request (2000, the bind_port in the 
reply was ignored since the port you requested was not 0) is inconsistent with 
the port you asked in the ssh_channel_open_reverse_forward() (8080)


You should at least receive a tcpip-forward channel open request from server on 
the client in ssh_channel_accept_forward but your logs doesn't show it.

I would advice to use a event object with callback also on client side and use 
a callback instead of ssh_channel_accept_forward.


Beware that your server tcpip-forward channel is bind to nothing, so even if 
the open request is successful, there won't be any data transfering.

The regular way is to start to bind and listen a socket on a local port when 
receiving the global request on server and then opening the channel when 
something connects to the socket.


Regards,


Meng

________________________________
De : Martín Fernández <[email protected]>
Envoyé : jeudi 29 mars 2018 18:45:49
À : Meng Hourk Tan; [email protected]
Objet : RE: Global Request for tcpip reverse forward


Meng,

Thank you very much for your response!

Actually, I have tried that before. After sending the global response, calling 
`ssh_channel_open_reverse_forward`. Problem is that after calling the function, 
client and server get blocked. I’m sending a snippet of what I changed. Also, 
just for providing more information, this is the log from the server and client.


Server:
[2018/03/29 13:41:32.810991, 2] ssh_packet_global_request:  Calling callback 
for SSH_MSG_GLOBAL_REQUEST tcpip-forward 1 0.0.0.0:2000
[2018/03/29 13:41:32.811025, 3] ssh_socket_unbuffered_write:  Enabling POLLOUT 
for socket
[2018/03/29 13:41:32.811036, 3] packet_send2:  packet: wrote 
[len=12,padding=10,comp=1,payload=1]
[2018/03/29 13:41:32.811077, 2] channel_open:  Creating a channel 43 with 64000 
window and 32768 max packet
[2018/03/29 13:41:32.811104, 3] packet_send2:  packet: wrote 
[len=76,padding=9,comp=66,payload=66]
[2018/03/29 13:41:32.811114, 3] channel_open:  Sent a SSH_MSG_CHANNEL_OPEN type 
forwarded-tcpip for channel 43

Client:
[2018/03/29 13:41:32.810891, 3] global_request:  Sent a SSH_MSG_GLOBAL_REQUEST 
tcpip-forward
[2018/03/29 13:41:32.811106, 3] ssh_packet_socket_callback:  packet: read type 
81 [len=12,padding=10,comp=1,payload=1]
[2018/03/29 13:41:32.811121, 3] ssh_packet_process:  Dispatching handler for 
packet type 81
[2018/03/29 13:41:32.811130, 3] ssh_request_success:  Received 
SSH_REQUEST_SUCCESS
[2018/03/29 13:41:32.811139, 2] global_request:  Global request tcpip-forward 
success


/**
* @brief Global request callback
*
* @param session
* @param message
* @param userdata
*/
static void handle_global_request(ssh_session session, ssh_message message, 
void *userdata) {
ssh_message_global_request_reply_success(message, 8080);

ssh_channel channel = ssh_channel_new(session);
int result = ssh_channel_open_reverse_forward(channel, "localhost", 8080, 
"localhost", 8080);

printf("RESULT %d\n", result);
}

Thanks before hand!

Martín

On Thu, Mar 29, 2018 at 7:22 AM Meng Hourk Tan <Meng Hourk Tan 
<mailto:Meng%20Hourk%20Tan%20<[email protected]>> > wrote:

Hi Martin,


I think your code lacks one step on server side:

After the Server handles the request using callback global_request_function and 
responds with ssh_message_global_request_reply_success,

You need to create a new channel and call ssh_channel_open_reverse_forward() on 
this channel.

Then the client will receive the opening request of the reverse port forwarding 
channel.

Hope it helps,

Regards,


Meng

________________________________
De : Martín Fernández <[email protected]>
Envoyé : lundi 26 mars 2018 08:20:23
À : [email protected]
Objet : Global Request for tcpip reverse forward


Hello!

This is my first time writing in the mailing list, I’m really new to libssh.

I’m trying to get a server and client implementation for reverse port 
forwarding.

My understanding it that client requests the server for reverse port forwarding 
in a given port, server handles the petition and is responsible for managing 
the socket and redirecting data from socket to ssh channel. Client is 
responsible for reading ssh channel and sending data to the local server.

I have successfully managed to get authentication between client and server 
work correctly.

The part I’m probably missing something is on how to handle the global request 
from client and how to pull for data in the client.

Basic pseudo code that I’m doing.

- Client send global request to server using `ssh_channel_listen_forward`.
- Server handles the request using callback global_request_function and 
responds with ssh_message_global_request_reply_success
- Client calls ssh_channel_accept_forward to get a new channel

My problem is that `ssh_channel_accept_forward` never returns. I’m not sure If 
I’m missing something on the server side to initiate the channel. I know that I 
then need to redirect data between socket and channel but first I think I need 
to get a valid channel for forwarding right ?

My complete code can be found here: 
https://gist.github.com/bilby91/22d5cc5db0e6118f06d6d35051c32cc6

Thanks before hand!

Martín



From 10932254543593de736512cc22c506f1e57e05b7 Mon Sep 17 00:00:00 2001
From: Meng Tan <[email protected]>
Date: Wed, 18 Apr 2018 11:51:56 +0200
Subject: [PATCH] Add open forwarded-tcpip channel request in client callbacks

Signed-off-by: Meng Tan <[email protected]>
---
 include/libssh/callbacks.h | 18 ++++++++++++++++++
 src/messages.c             | 17 ++++++++++++++++-
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/include/libssh/callbacks.h b/include/libssh/callbacks.h
index 4e71b3b9..3778cda4 100644
--- a/include/libssh/callbacks.h
+++ b/include/libssh/callbacks.h
@@ -137,6 +137,21 @@ typedef ssh_channel (*ssh_channel_open_request_auth_agent_callback) (ssh_session
       void *userdata);
 
 /**
+ * @brief Handles an SSH new channel open "forward-tcpip" request. This happens when the server
+ * sends back an "forward-tcpip" connection attempt. This is a client-side API
+ * @param session current session handler
+ * @param userdata Userdata to be passed to the callback function.
+ * @returns a valid ssh_channel handle if the request is to be allowed
+ * @returns NULL if the request should not be allowed
+ * @warning The channel pointer returned by this callback must be closed by the application.
+ */
+typedef ssh_channel (*ssh_channel_open_request_forwarded_tcpip_callback) (
+        ssh_session session,
+        const char *destination, uint16_t destination_port, const char *originator,
+        uint16_t originator_port, void *userdata);
+
+
+/**
  * The structure to replace libssh functions with appropriate callbacks.
  */
 struct ssh_callbacks_struct {
@@ -169,6 +184,9 @@ struct ssh_callbacks_struct {
   /** This function will be called when an incoming "auth-agent" request is received.
    */
   ssh_channel_open_request_auth_agent_callback channel_open_request_auth_agent_function;
+  /** This function will be called when an incoming forwarded tcpip channel request is received.
+   */
+  ssh_channel_open_request_forwarded_tcpip_callback channel_open_request_forwarded_tcpip_function;
 };
 typedef struct ssh_callbacks_struct *ssh_callbacks;
 
diff --git a/src/messages.c b/src/messages.c
index af885314..473cd4f9 100644
--- a/src/messages.c
+++ b/src/messages.c
@@ -340,6 +340,21 @@ static int ssh_execute_client_request(ssh_session session, ssh_message msg)
         }
 
         return SSH_OK;
+    } else if (msg->type == SSH_REQUEST_CHANNEL_OPEN
+               && msg->channel_request_open.type == SSH_CHANNEL_FORWARDED_TCPIP
+               && ssh_callbacks_exists(session->common.callbacks, channel_open_request_forwarded_tcpip_function)) {
+        channel = session->common.callbacks->channel_open_request_forwarded_tcpip_function(session,msg->channel_request_open.destination,
+                                                                                           msg->channel_request_open.destination_port,
+                                                                                           msg->channel_request_open.originator,
+                                                                                           msg->channel_request_open.originator_port,
+                                                                                           session->common.callbacks->userdata);
+        if (channel != NULL) {
+            rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel);
+            return rc;
+        } else {
+            ssh_message_reply_default(msg);
+        }
+        return SSH_OK;
     }
 
     return rc;
@@ -1075,7 +1090,7 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open){
     ssh_set_error(session,SSH_FATAL, "Invalid state when receiving channel open request (must be authenticated)");
     goto error;
   }
-  
+
   if (strcmp(type_c,"session") == 0) {
     msg->channel_request_open.type = SSH_CHANNEL_SESSION;
     SAFE_FREE(type_c);
-- 
2.11.0

Reply via email to