Reputation: 3487
I have a C# application that needs to run certain commands on a piece of hardware over SSH. The application is using SSH.Net
to make the connection, send the command, and the read the result. I have this working if I connect to my local machine using OpenSSH. Finally, I wanted to go a step further and setup my own SSH server so I could simulate multiple hardware devices at one time (need to simulate having 50+ devices to SSH into).
For this I have setup a simple SSH server using nodejs and the ssh2
package. So far I have the client connected, authenticated (all connections are accepted for now), and I can see a session
object being created. Although where I'm hitting a wall is with the execution of commands sent by the client. I noticed that ssh2
has an event for exec
on the session
object but this never seems to trigger (regardless of what i put in SSH.Net
's ShellStream
).
The C# client code that initiates the connection is the following (command
is already defined that the command string to be executed):
using(SshClient client = new SshClient(hostname, port, username, password))
{
try
{
client.ErrorOccurred += Client_ErrorOccurred;
client.Connect();
ShellStream shellStream = client.CreateShellStream("xterm", Columns, Rows, Width, Height, BufferSize, terminalModes);
var initialPrompt = await ReadDataAsync(shellStream);
// The command I write to the stream will get executed on OpenSSH
// but not on the nodejs SSH server
shellStream.WriteLine(command);
var output = await ReadDataAsync(shellStream);
var results = $"Command: {command} \nResult: {output}";
client.Disconnect();
Console.WriteLine($"Prompt: {initialPrompt} \n{results}\n");
}
catch (Exception ex)
{
Console.WriteLine($"Exception during SSH connection: {ex.ToString()}");
}
}
The nodejs server code that set ups the ssh2 server is following:
new ssh2.Server({
hostKeys: [fs.readFileSync('host.key')]
}, function(client) {
console.log('Client connected!');
client.on('authentication', function(ctx) {
ctx.accept();
}).on('ready', function() {
console.log('Client authenticated!');
client.on('session', function(accept, reject) {
var session = accept();
// Code gets here but never triggers the exec
session.once('exec', function(accept, reject, info) {
console.log('Client wants to execute: ' + inspect(info.command));
var stream = accept();
stream.write('returned result\n');
stream.exit(0);
stream.end();
});
});
}).on('end', function() {
console.log('Client disconnected');
});
}).listen(port, '127.0.0.1', function() {
console.log('Listening on port ' + this.address().port);
});
I have seen various ssh2
client examples invoking a client.exec
function but I was assuming that it did not matter that my client was not using the ssh2
node package. Is there something that I'm missing here?
Upvotes: 3
Views: 820
Reputation: 202534
The "exec" Node.js server session event is for "non-interactive (exec) command execution". By which they most likely mean SSH "exec" channel (which is intended for "non-interactive command execution").
To execute a command using "exec" SSH channel in SSH.NET, use SshClient.RunCommand
.
On the contrary SshClient.CreateShellStream
uses SSH "shell" channel, which is intended for implementing an interactive shell session.
For that, you need to handle "shell" Node.js server session event.
Upvotes: 1