0 votes
by (120 points)

Hi

I need to build a SSH-connection to the host by a proxy with ProxyType Local.
Usage of Rebex.Net with C# .Net.

Is this possible?
If yes, could you support me with a Code-Example?

Please let me know too if this type of ssh-connection wont be possible with Rebex.Net. Thanks!

Details :
I do this connection manually with putty with settings as follows

Server: server.shared.net

ProxySettings
Proxy: proxy.shared.net
ProxyType!!: Local
Telnet command: plink.exe -agent -l %user -pw %pass %proxyhost -nc %host:%port

Connection-SSH Settings
Tunnels: Fowarded ports D10000 (Dynamic Port 10000)

short form, it's in this way: https://www.vscentrum.be/client/windows/putty-proxy

Thanks in advance
Phil

1 Answer

0 votes
by (144k points)

It looks like you are trying to connect to an SSH server through an intermediate SSH server (using it as a proxy).

This is supported by Rebex SSH, but it's done differently than in PuTTY, which has to launch an external utility to establish the tunnel.

Instead, just use SshSession object to establish a connection to the SSH server you would like to use as a proxy:

var session = new SshSession();
session.Connect("proxy.shared.net");
session.Authenticate(proxyUsername, proxyPassword);

Then, use Ssh class to connect to the target server, but instruct it to connect via the proxy:

var ssh = new Ssh();
ssh.SetSocketFactory(session.ToSocketFactory());
ssh.Connect("server.shared.net");
ssh.Login(serverUername, serverPassword);

Now, you have an instance of Ssh that can be used as if it was connected directly.

by (120 points)
thanks,
this solution works great and it's possible to execute some "normal" commands. (e.g. touch file etc.)

unfortunately in my case I have to make a sudo to a "service-account" on the "server.shared.net" too.
e.g. sudo -u service-account bash

Then I'm receiving a "Response reading timed out." after a few seconds.

Could you support with an extended solution for this kind of command-usage?

Thanks in advance!
by (120 points)
Found it in your doku :-)
https://www.rebex.net/terminal-emulation.net/features/scripting.aspx

Scripting scripting = ssh.StartScripting();
scripting.SendCommand("sudo -u service-account bash");
scripting.Close();
by (144k points)
If you close the connection after calling SendCommand, there is no way to determine whether it actually succeeded. I would suggest calling (for example) scripting.ReadLine() or scripting.ReadUntil(...) to make sure there was the expected response.
by (120 points)
scripting.ReadLine() or scripting.ReadUntil(...) on "sudo -u service-account bash" gives a "Response reading timed out." unfortunately.
Other commands are working!

Doing it with a workaround, maybe not very stylish ;-)

Scripting scripting = ssh.StartScripting();
scripting.SendCommand("sudo -u service-account bash");

// receive response
var response = string.Empty;

// ReadUntilPrompt dont work for sudo-command
// try catch for other commands which fail similar like sudo
if (!command.StartsWith("sudo"))
{
    try
    {
        response = scripting.ReadUntilPrompt();
    }
    catch (Exception e)
    {
        response = e.Message;
    }
}

Debug.Print($"Response: {response}");

scripting.Close();
by (144k points)
It would be very helpful to determine what response your sudo command actually produces. Then, it should be possible to choose an appropriate scripting.ReadSomething method that reads the expected response. Once possible way to achieve this is to use Ssh object's LogWriter property, as described at https://www.rebex.net/kb/logging/ to create a communication log. In this case, LogLevel.Verbose would be needed to get the transmitted data. However, because LogLevel.Verbose are so verbose that they might contain credentials, it would be best to set ssh.LogWriter just prior to calling ssh.StartScripting (and if you would like to share the log with us, edit out any sensitive data first).
by (120 points)
edited by
There is the log:

Login with: personalUser
Sudo with: serviceUser

Command1: sudo -u serviceUser bash
Command2: exit
(both commands have the same behaviour.
This Log is with Default-Timeouts.
When Timeout has been set to e.g. 5 hours, the the scripting.ReadUntilPrompt(); waits 5 hours !)

Hope this helps

2018-06-14 15:14:07.529 VERBOSE VirtualTerminal(0)[7] Scripting: DetectPrompt: found a prompt.
2018-06-14 15:14:07.532 VERBOSE VirtualTerminal(0)[7] Scripting: DetectPrompt: Prompt resolved as regex:\[personalUser@r03-n04\ .*\$\ .
2018-06-14 15:14:07.532 DEBUG VirtualTerminal(0)[7] Scripting: SendCommand(sudo -u serviceUser bash )
2018-06-14 15:14:07.533 VERBOSE Ssh(1)[7] SSH: Sending packet SSH_MSG_CHANNEL_DATA (33 bytes).
 0000 |5E-00-00-00-00-00-00-00 18-73-75-64-6F-20-2D-75| ^........sudo -u
 0010 |20-73-72-76-2D-6F-72-69 6F-6E-20-62-61-73-68-20|  serviceUser bash
 0020 |0D                                             | .
2018-06-14 15:14:07.533 DEBUG Ssh(1)[7] Info: Sent 24 bytes of data.
2018-06-14 15:14:07.533 VERBOSE Ssh(1)[7] Info: Sent data:
 0000 |73-75-64-6F-20-2D-75-20 73-72-76-2D-6F-72-69-6F| sudo -u service
 0010 |6E-20-62-61-73-68-20-0D                        | User bash .
2018-06-14 15:14:07.533 DEBUG VirtualTerminal(0)[7] Scripting: WaitFor(Line)
2018-06-14 15:14:07.533 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: polling data for max 60000 ms.
2018-06-14 15:14:07.544 VERBOSE Ssh(1)[29] SSH: Received packet SSH_MSG_CHANNEL_DATA (34 bytes).
 0000 |5E-00-00-00-00-00-00-00 19-73-75-64-6F-20-2D-75| ^........sudo -u
 0010 |20-73-72-76-2D-6F-72-69 6F-6E-20-62-61-73-68-20|  serviceUser bash
 0020 |0D-0A                                          | ..
2018-06-14 15:14:07.544 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: data received, reset last data received time stamp.
2018-06-14 15:14:07.544 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: processing received data.
2018-06-14 15:14:07.544 DEBUG Ssh(1)[7] Info: Received 25 bytes of data.
2018-06-14 15:14:07.544 VERBOSE Ssh(1)[7] Info: Received data:
 0000 |73-75-64-6F-20-2D-75-20 73-72-76-2D-6F-72-69-6F| sudo -u service
 0010 |6E-20-62-61-73-68-20-0D 0A                     | User bash ..
2018-06-14 15:14:07.545 DEBUG VirtualTerminal(0)[7] Scripting: ReadUntil(prompt: 'regex:\[personalUser@r03-n04\ .*\$\ ')
2018-06-14 15:14:07.545 DEBUG VirtualTerminal(0)[7] Scripting: WaitFor(prompt: 'regex:\[personalUser@r03-n04\ .*\$\ ')
2018-06-14 15:14:07.545 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: polling data for max 50 ms.
2018-06-14 15:14:07.601 VERBOSE Ssh(1)[29] SSH: Received packet SSH_MSG_CHANNEL_DATA (27 bytes).
 0000 |5E-00-00-00-00-00-00-00 12-1B-5B-3F-31-30-33-34| ^.........[?1034
 0010 |68-62-61-73-68-2D-34-2E 32-24-20               | hbash-4.2$
2018-06-14 15:14:07.601 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: data received, reset last data received time stamp.
2018-06-14 15:14:07.601 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: processing received data.
2018-06-14 15:14:07.601 DEBUG Ssh(1)[7] Info: Received 18 bytes of data.
2018-06-14 15:14:07.601 VERBOSE Ssh(1)[7] Info: Received data:
 0000 |1B-5B-3F-31-30-33-34-68 62-61-73-68-2D-34-2E-32| .[?1034hbash-4.2
 0010 |24-20                                          | $
2018-06-14 15:14:07.603 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: polling data for max 50 ms.
2018-06-14 15:14:07.653 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: no data received in 50 ms.
2018-06-14 15:14:07.653 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: last data received 62 ms ago.
2018-06-14 15:14:07.653 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: evaluating ScriptEvent.Delay and/or ScriptEvent.Duration.
2018-06-14 15:14:07.653 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: ScriptEvent.Delay and/or ScriptEvent.Duration is not enough to complete all script events. Continue wait for other data.
2018-06-14 15:14:07.653 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: polling data for max 59938 ms.
2018-06-14 15:15:07.605 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: no data received in 59938 ms.
2018-06-14 15:15:07.605 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: last data received 60015 ms ago.
2018-06-14 15:15:07.605 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: ScriptEvent.Timeout successfuly evaluated.
2018-06-14 15:15:07.752 DEBUG VirtualTerminal(0)[7] Scripting: DetectPrompt()
2018-06-14 15:15:07.752 VERBOSE VirtualTerminal(0)[7] Scripting: DetectPrompt: starting detection loop.
2018-06-14 15:15:07.752 VERBOSE VirtualTerminal(0)[7] Scripting: DetectPrompt: another line is needed. Sending ENTER.
2018-06-14 15:15:07.752 VERBOSE Ssh(1)[7] SSH: Sending packet SSH_MSG_CHANNEL_DATA (10 bytes).
 0000 |5E-00-00-00-00-00-00-00 01-0D                  | ^.........
2018-06-14 15:15:07.752 DEBUG Ssh(1)[7] Info: Sent 1 bytes of data.
2018-06-14 15:15:07.752 VERBOSE Ssh(1)[7] Info: Sent data:
 0000 |0D                                             | .
2018-06-14 15:15:07.752 VERBOSE VirtualTerminal(0)[7] Scripting: DetectPrompt: reading data for prompt detection.
2018-06-14 15:15:07.752 DEBUG VirtualTerminal(0)[7] Scripting: WaitFor(delay: 400)
2018-06-14 15:15:07.752 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: polling data for max 400 ms.
2018-06-14 15:15:07.764 VERBOSE Ssh(1)[29] SSH: Received packet SSH_MSG_CHANNEL_DATA (21 bytes).
 0000 |5E-00-00-00-00-00-00-00 0C-0D-0A-62-61-73-68-2D| ^..........bash-
 0010 |34-2E-32-24-20                                 | 4.2$
2018-06-14 15:15:07.764 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: data received, reset last data received time stamp.
2018-06-14 15:15:07.764 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: processing received data.
2018-06-14 15:15:07.764 DEBUG Ssh(1)[7] Info: Received 12 bytes of data.
2018-06-14 15:15:07.764 VERBOSE Ssh(1)[7] Info: Received data:
 0000 |0D-0A-62-61-73-68-2D-34 2E-32-24-20            | ..bash-4.2$
2018-06-14 15:15:07.764 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: polling data for max 400 ms.
2018-06-14 15:15:08.175 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: no data received in 400 ms.
2018-06-14 15:15:08.175 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: last data received 406 ms ago.
2018-06-14 15:15:08.175 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: evaluating ScriptEvent.Delay and/or ScriptEvent.Duration.
2018-06-14 15:15:08.175 VERBOSE VirtualTerminal(0)[7] Scripting: WaitFor: ScriptEvent.Delay and/or ScriptEvent.Duration successfuly evaluated.
by (70.2k points)
Thank you for the verbose log. It showed what you were doing and what the server replied. The situation is following:

1. The DetectPrompt() method tries to determine current prompt by sending ENTER and comparing two last line. If the lines are equal, the string before cursor is taken as prompt. This is working for you.

2. The WaitFor(Prompt) method reads data from server and returns when currently set prompt is found. This would work for you if the command not changed the displayed prompt.

After connect, your prompt is "[personalUser@r03-n04 ~]$ " (it is successfully detected).
When you execute "sudo -u serviceUser bash" the prompt is changed to "bash-4.2$ ".
When you call DetectPrompt() the prompt is successfully detected to "bash-4.2$ ".
When you execute "exit" the bash is terminated and original prompt is displayed, which is "[personalUser@r03-n04 ~]$ ".


From the knowledge above, I suggest you this solution:

    // detect current prompt
    scripting.DetectPrompt();

    // save original prompt
    string originalPrompt = scripting.Prompt;

    // run new bash
    scripting.SendCommand("sudo -u serviceUser bash");

    // wait for prompt or no data are received for 5 seconds
    var m = scripting.WaitFor(ScriptEvent.Prompt, ScriptEvent.Delay(5 * 1000));
    if (m.IsPrompt)
    {
        // starting new bash failed -> display error (received data)
        Console.WriteLine(scripting.ReceivedData);
        return;
    }
    else
    {
        // no data for 5 seconds -> it seems new bash was started
        // detect prompt of new bash
        scripting.DetectPrompt();
    }

    // execute commands in new bash
    //scripting.SendCommand("...");

    // wait for responses as usual
    //scripting.WaitFor(ScriptEvent.Prompt);

    // exit new bash
    scripting.SendCommand("exit");

    // set original prompt first
    scripting.Prompt = originalPrompt;
    scripting.WaitFor(ScriptEvent.Prompt);

    // execute commands in original bash or finish...
by (120 points)
Great explanation, thanks !
...