Using the Node module SSH2 with shell - node.js

My aim is to make a web application that allows it's user to connect to an SSH server remotely, i.e. without installing an SSH client on their computer. So this means my server will be an intermediate interface between the user and their SSH server/s.
I found an SSH2 module for node: https://github.com/mscdex/ssh2
I figured the most appropriate method of connecting was using the shell() method.
The following is a basic attempt to get a shell working.
var Connection = require('ssh2');
var c = new Connection();
c.on('ready', function() {
c.shell(onShell);
});
var onShell = function(err, stream) {
if (err != null) {
console.log('error: ' + err);
}
stream.on('readable', function() {
var chunk;
while (null !== (chunk = stream.read())) {
console.log('got %d bytes of data', chunk.length);
}
});
stream.write('ls\r\n');
console.log('Shell');
}
c.connect({
host: 'localhost',
port: 22,
username: 'matt',
password: 'password'
});
It connects fine, and there are no errors, but the "got %d bytes of data" does not show. How can I fix this?
Furthermore would this method be sensible in a large scale application with potentially many simultaneous different connections?

ssh2 currently does not use streams2 yet because things get tricky because of the two (stdout and stderr) "sub-"streams and trying to handle backpressure in a sane way. I am still hoping I can find some solution via streams2 though.
For now, you will have to listen for 'data', 'drain', etc. events instead.
UPDATE: ssh2 v0.3.x now supports streams2.

I wrote a wrapper class for ssh2 that handles running multiple commands in a SSH shell session and can SSH tunnel to multiple hosts using nested host objects. Each hosts config object has its own commands, command event handlers, end of session handler and authentication parameters. Commands responses can be checked for prompts or results that require extra handling or addition/removal of commands from a commands array. It also times out if a command produces an unexpected prompt that is not handled and would normally cause the process to hang waiting for a response it will never get.
Check it out:
Extensive info in the readme, test examples provided, additional info in the git wiki.
https://www.npmjs.org/package/ssh2shell
https://github.com/cmp-202/ssh2shell

Related

trying to connect to TCP server using Node.js

I'm trying to connect to a server/specific port using Node.js, and I don't even get past var net = require('net');
I'm using Node.js v16.15.0.
Welcome to Node.js v16.15.0.
When I use the command above, I receive UNDEFINED. As far as I know, I've installed everything I need (including socket.io), and I'm working within the Node.js environment in iTerm.
My goal is to connect to a TCP server, receive a list of files, and then download each of them over a persistent socket. But I'm a little stuck as I can't even seem to get into the TCP server in the first place.
This is what I think I'm supposed to run to get in (obviously with my correct port and IP info which is omitted below).
var HOST = 'IP';
var PORT = 'PORT'
var FILEPATH = 'myfilepathhereIwilltweakitwhenIgettothispoint';
Can anyone point me in the right direction?
From what you said, I think you are trying to code NodeJS script within the NodeJS executable start in command line. You get an UNDEFINED because you imported the library into your variable and this assignment does have any value, so it is UNDEFINED. You can read more about this in this subject : link
But what we usually do in NodeJS development is creating a file, let's call it index.js. Inside that file we are writing our code, let's say :
const net = require('net');
const client = net.createConnection({ port: 8124 }, () => {
// 'connect' listener.
console.log('connected to server!');
client.write('world!\r\n');
});
client.on('data', (data) => {
console.log(data.toString());
client.end();
});
client.on('end', () => {
console.log('disconnected from server');
});
Code sample from NodeJS Documentation.
Then we want to run our code by using the command line like this : node path/to/index.js.
Hope it helps !

How to disconnect ssh connection by using node-ssh in node js

Can anyone help me, how t disconnect ssh connection using node-ssh module in node js. Also how to handle error.
my code is
driver = require('node-ssh');
ssh = new driver({
host: '192.168.*.*',
username: 'user',
password: 'password',
privateKey : require('fs').readFileSync('/tmp/my_key')
});
ssh.connect().then(function() {
/*
some code
*/
},function(error) {
console.log(error);
});
Pls help.
Use the dispose method. Example:
const node_ssh = require('node-ssh');
const ssh = new node_ssh();
ssh.connect({
host: 'XXX',
username: 'YYY',
privateKey: 'ZZZ'
}).then(resp => {
console.log(resp);
ssh.dispose();
});
The 'node-ssh' wrapper doesn't seem to provide an 'end' function, or a way to access the underlying ssh2 connection object. That leaves you with a couple options:
Fork the source, write an 'end' method, and issue a pull request to the node-ssh wrapper so that future users can use the wrapper and end the connections. Alternatively, you can create an issue and wait for someone else to create the functionality if/when they deem it necessary.
Use the underlying ssh2 library instead. It exposes a lot more functionality to you, including an 'end' method, to close the connection, but uses callbacks instead of promises, which would require you to refactor your code.
Additionally, you could add the following to your code, though this is very heavily not recommended, as it's messing with a prototype you don't own and could ruin compatibility with future versions of the node-ssh module:
driver.prototype.end = function() {
this.Connection.end()
this.Connected = false
}
you can then call ssh.end() to close the connection.
I've asked directly the creator of the library, here i report the answer:
"Note: If anything of the ssh2 object is not implemented and I am taking more time than I should, You can always use MySSH.Connection.close()"
Issue#9
Then he has done a commit and now you have your method!
ssh.end();
I struggle for these the ssh to a remote server frequently, and the connection can not be closed by ssh.compose() in the ssh-node package, and I find remote windows ssh server still generate many processes named sshd process and not be closed, and after ssh.compose, the node.js will throw the error Error: read ECONNRESET at TCP.onStreamRead which can not be caught by code.I find many references, it could be the TCP connection is still working on and not be closed. So I try to refer to the ssh-node code and use the
ssh.connection.destroy()
which point to the Client.prototype.destroy method in ssh2 packageļ¼Œ so the error Error: read ECONNRESET at TCP.onStreamRead will disappeared, and the connection will be closed totally.

connecting to RedisToGo on Heroku thru Nodejs [duplicate]

I'm using Redis To Go in combination with the https://github.com/mranney/node_redis library. Redis gives me a url that looks like redis://me:978287c0b670694673d045f08b2e0371#icefish.redistogo.com:9393 but I don't know how to use it as createClient() only takes the host and the port.
I believe that the scheme for the URL you have is:
redis://username:password#host:port.
I don't believe username is used. node_redis provides two methods that you'll use to log in: createClient and auth. There are details in the readme, but for reference here is the relevant portion:
redis.createClient(port, host, options)
Create a new client connection. port defaults to 6379 and host
defaults to 127.0.0.1. If you have redis-server running on the
same computer as node, then the defaults for port and host are
probably fine. options in an object with the following possible
properties:
parser: which Redis protocol reply parser to use. Defaults to
hiredis if that module is installed. This may also be set to
javascript.
return_buffers: defaults to false. If set to true, then bulk
data replies will be returned as node Buffer objects instead of
JavaScript Strings.
createClient() returns a RedisClient object that is named client
in all of the examples here.
client.auth(password, callback)
When connecting to Redis servers that require authentication, the
AUTH command must be sent as the first command after connecting.
This can be tricky to coordinate with reconnections, the ready check,
etc. To make this easier, client.auth() stashes password and will
send it after each connection, including reconnections. callback is
invoked only once, after the response to the very first AUTH command
sent.
I also had to add the parameter no_ready_check: true to the call to redis.createClient().
client = redis.createClient(settings.redis.port,
settings.redis.host,
{no_ready_check: true});
if (settings.redis.password) {
client.auth(settings.redis.password, function() {
console.log('Redis client connected');
});
}

Node.js Outgoing Http request connection limit (cannot make connections more than five)

I'm building a data transfer proxy server using node.js.
It pipes client's request to swift object storage server using http(s) REST API.
It works fine for the individual request but when the outgoing
ESTABLISHED tcp connection for the same destination and port(443)
reaches five, it cannot create any new connection.
It does not seem to be a problem of O/S, because I've tried to create more than 10 connections using java servlet and it works fine.
I've tried to set maximum sockets for globalAgent like below, but it does not change anything.
http.globalAgent.maxSockets = 500;
https.globalAgent.maxSockets = 500;
Here is a part of my source code.
app.post('/download*', function(req, res){
/***********************************************************
* Some codes here to create new request option
***********************************************************/
var client = https.request(reqOptions, function(swiftRes) {
var buffers = [];
res.header('Content-Length', swiftRes.headers['content-length']);
res.header('Content-Type', swiftRes.headers['content-type']);
res.header('range', swiftRes.headers['range']);
res.header('connection', swiftRes.headers['connection']);
swiftRes.pipe(res);
swiftRes.on('end', function(err){
res.end();
});
});
client.on('error', function(err) {
callback && callback(err);
client.end(err);
clog.error('######### Swift Client Error event occurred. Process EXIT ');
});
client.end();
});
I hope I can get the solution for this problem.
Thanks in advance.
Usually, the change of the maxSockets should solve your problem, try it with a value a little bit lower.
https.globalAgent.maxSockets=20;
If that does not solve your problem, try to turn off pooling for the connections. Add the key agent with the value false to the options to the request. Keep in mind that Node.js uses the pooling to use keep-alive connection.
//Your option code
reqOptions.agent=false;

Connecting to RedisToGo through Node.JS

I'm using Redis To Go in combination with the https://github.com/mranney/node_redis library. Redis gives me a url that looks like redis://me:978287c0b670694673d045f08b2e0371#icefish.redistogo.com:9393 but I don't know how to use it as createClient() only takes the host and the port.
I believe that the scheme for the URL you have is:
redis://username:password#host:port.
I don't believe username is used. node_redis provides two methods that you'll use to log in: createClient and auth. There are details in the readme, but for reference here is the relevant portion:
redis.createClient(port, host, options)
Create a new client connection. port defaults to 6379 and host
defaults to 127.0.0.1. If you have redis-server running on the
same computer as node, then the defaults for port and host are
probably fine. options in an object with the following possible
properties:
parser: which Redis protocol reply parser to use. Defaults to
hiredis if that module is installed. This may also be set to
javascript.
return_buffers: defaults to false. If set to true, then bulk
data replies will be returned as node Buffer objects instead of
JavaScript Strings.
createClient() returns a RedisClient object that is named client
in all of the examples here.
client.auth(password, callback)
When connecting to Redis servers that require authentication, the
AUTH command must be sent as the first command after connecting.
This can be tricky to coordinate with reconnections, the ready check,
etc. To make this easier, client.auth() stashes password and will
send it after each connection, including reconnections. callback is
invoked only once, after the response to the very first AUTH command
sent.
I also had to add the parameter no_ready_check: true to the call to redis.createClient().
client = redis.createClient(settings.redis.port,
settings.redis.host,
{no_ready_check: true});
if (settings.redis.password) {
client.auth(settings.redis.password, function() {
console.log('Redis client connected');
});
}

Resources