Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
telnet-client
Advanced tools
The telnet-client npm package is a simple and easy-to-use library for creating and managing Telnet connections in Node.js. It allows you to connect to Telnet servers, send commands, and receive responses, making it useful for automating tasks, remote server management, and network device configuration.
Establishing a Telnet Connection
This feature allows you to establish a connection to a Telnet server using specified parameters such as host, port, shell prompt, and timeout.
const Telnet = require('telnet-client');
let connection = new Telnet();
let params = {
host: '127.0.0.1',
port: 23,
shellPrompt: '/ # ',
timeout: 1500
};
connection.connect(params)
.then(() => {
console.log('Connected to the Telnet server');
})
.catch((error) => {
console.error('Connection failed:', error);
});
Sending Commands
Once connected, you can send commands to the Telnet server and handle the responses. This is useful for executing remote commands and automating tasks.
connection.send('ls -l')
.then((response) => {
console.log('Command response:', response);
})
.catch((error) => {
console.error('Command failed:', error);
});
Handling Connection Events
You can handle various connection events such as timeout and close to manage the connection lifecycle and handle errors or disconnections gracefully.
connection.on('timeout', () => {
console.log('Connection timed out');
connection.end();
});
connection.on('close', () => {
console.log('Connection closed');
});
node-telnet-client is another Telnet client library for Node.js. It offers similar functionalities to telnet-client, such as establishing connections, sending commands, and handling responses. However, it provides a more extensive set of options for connection parameters and event handling, making it a bit more flexible for advanced use cases.
telnet-stream is a low-level Telnet client library that provides a stream-based interface for Telnet communication. It is more suitable for developers who need fine-grained control over the Telnet protocol and want to build custom Telnet clients. Compared to telnet-client, it requires more effort to set up and use but offers greater flexibility.
A simple telnet client for Node.js
Locally in your project or globally:
npm install telnet-client
npm install -g telnet-client
Note: As of version 2.0.0 of this API, native ES6 promises are returned, not Bluebird promises.
'use strict'
const { Telnet } = require('telnet-client');
(async function () {
const connection = new Telnet()
// these parameters are just examples and most probably won't work for your use-case.
const params = {
host: '127.0.0.1',
port: 23,
shellPrompt: '/ # ', // or negotiationMandatory: false
timeout: 1500
}
try {
await connection.connect(params)
} catch (error) {
// handle the throw (timeout)
}
const res = await connection.exec('uptime')
console.log('async result:', res)
})()
const { Telnet } = require('telnet-client')
const connection = new Telnet()
// these parameters are just examples and most probably won't work for your use-case.
const params = {
host: '127.0.0.1',
port: 23,
shellPrompt: '/ # ', // or negotiationMandatory: false
timeout: 1500
}
connection.on('ready', prompt => {
connection.exec(cmd, (err, response) => {
console.log(response)
})
})
connection.on('timeout', () => {
console.log('socket timeout!')
connection.end()
})
connection.on('close', () => {
console.log('connection closed')
})
connection.connect(params)
Note: As of version 2.0.0 of this API, native ES6 promises are returned, not Bluebird promises.
const { Telnet } = require('telnet-client')
const connection = new Telnet()
// these parameters are just examples and most probably won't work for your use-case.
const params = {
host: '127.0.0.1',
port: 23,
shellPrompt: '/ # ', // or negotiationMandatory: false
timeout: 1500
}
connection.connect(params)
.then(prompt => {
connection.exec(cmd)
.then(res => {
console.log('promises result:', res)
})
}, error => {
console.log('promises reject:', error)
})
.catch(error => {
// handle the throw (timeout)
})
const co = require('co')
const toBluebird = require("to-bluebird")
const { Telnet } = require('telnet-client')
const connection = new Telnet()
// these parameters are just examples and most probably won't work for your use-case.
const params = {
host: '127.0.0.1',
port: 23,
shellPrompt: '/ # ', // or negotiationMandatory: false
timeout: 1500,
// removeEcho: 4
}
// using 'co'
co(function*() {
try {
yield connection.connect(params)
} catch (error) {
// handle the throw (timeout)
}
const res = yield connection.exec(cmd)
console.log('coroutine result:', const)
})
// using Promise
bluebird.coroutine(function*() {
try {
yield toBluebird(connection.connect(params))
} catch (error) {
// handle the throw (timeout)
}
let res = yield toBluebird(connection.exec(cmd))
console.log('coroutine result:', res)
})()
'use strict'
const { Telnet } = require('telnet-client')
process.on('unhandledRejection', error => {
throw error
})
async function run() {
let connection = new Telnet()
// these parameters are just examples and most probably won't work for your use-case.
let params = {
host: '127.0.0.1',
port: 23,
shellPrompt: '/ # ', // or negotiationMandatory: false
timeout: 1500
}
try {
await connection.connect(params)
} catch (error) {
// handle the throw (timeout)
}
let res = await connection.exec(cmd)
console.log('async result:', res)
}
run()
Please do not directly email any node-telnet-client committers with questions or problems. A community is best served when discussions are held in public.
If you have a problem, please search the issues to see if there's existing reports to the issue you're facing and if there's any known solutions.
I also offer professional (paid) support and services, so make sure to contact me for more info.
const { Telnet } = require('telnet-client')
const connection = new Telnet()
Creates a new TCP connection to the specified host, where 'options' is an object which can include following properties:
host
: Host the client should connect to. Defaults to '127.0.0.1'.port
: Port the client should connect to. Defaults to '23'.localAddress
: Local interface to bind for network connections. Defaults to an empty string. More information can be found here.socketConnectOptions
: Allows to pass an object, which can contain every property from Node's SocketConnectOpts. Defaults to an empty object. Properties defined inside this object will overwrite any of the three above properties. More information can be found here.timeout
: Sets the socket to timeout after the specified number of milliseconds.
of inactivity on the socket.shellPrompt
: Shell prompt that the host is using. Can be a string or an instance of RegExp. Defaults to regex /(?:\/ )?#\s/
. Use negotiationMandatory: false
if you don't need this.shellPrompt
to null
if you wish to use the send(…)
or write(…)
methods, ignoring the returned values, and instead relying on nextData()
or on('data'…
for feedback.loginPrompt
: Username/login prompt that the host is using. Can be a string or an instance of RegExp. Defaults to regex /login[: ]*$/i
.passwordPrompt
: Password/login prompt that the host is using. Can be a string or an instance of RegExp. Defaults to regex /Password: /i
.failedLoginMatch
: String or regex to match if your host provides login failure messages. Defaults to undefined.initialCtrlC
: Flag used to determine if an initial 0x03 (CTRL+C) should be sent when connected to server.initialLFCR
: Flag used to determine if an initial '\r\n' (CR+LF) should be sent when connected to server.username
: Username used to login. Defaults to 'root'.password
: Password used to login. Defaults to 'guest'.sock
: Duplex stream which can be used for connection hopping/reusing.irs
: Input record separator. A separator used to distinguish between lines of the response. Defaults to '\r\n'.ors
: Output record separator. A separator used to execute commands (break lines on input). Defaults to '\n'.echoLines
: The number of lines used to cut off the response. Defaults to 1. With a value of 0, no lines are cut off.stripShellPrompt
: Whether shell prompt should be excluded from the results. Defaults to true.pageSeparator
: The pattern used (and removed from final output) for breaking the number of lines on output. Defaults to '---- More'.negotiationMandatory
: Disable telnet negotiations if needed. Can be used with 'send' when telnet specification is not needed.
Telnet client will then basically act like a simple TCP client. Defaults to true.execTimeout
: A timeout used to wait for a server reply when the 'exec' method is used. Defaults to 2000 (ms).sendTimeout
: A timeout used to wait for a server reply when the 'send' method is used. Defaults to 2000 (ms).maxBufferLength
: Maximum buffer length in bytes which can be filled with response data. Defaults to 1M.terminalWidth
, terminalHeight
: When set to non-zero values, telnet-client
will respond to the host command IAC DO 0x18
(Terminal Type) with IAC WILL 0x18
, and it will respond to IAC DO 0x1F
with the given terminal width and height.newlineReplace
: If provided, incoming line breaks will be normalized to the provided character/string of characters.escapeHandler
: An optional function that receives escape sequences (either '0x1B'
and the next non-[
character, or '0x1B['
followed by every subsequent character up to and including the first ASCII letter) from the host. The function can either return null
, which means to take no action, or a string value to be sent to the host as a response.stripControls
: If set to true
, escape sequences and control characters (except for \t
, \n
, and \r
) will be stripped from incoming data. escapeHandler
is not affected.maxEndWait
: The maximum time, in milliseconds, to wait for a callback from socket.end(…)
after calling end()
. Defaults to 250 milliseconds.encoding
: (Experimental) The telnet protocol is designed mainly for 7-bit ASCII characters, and a default encoding used is 'ascii'
. You can attempt to use other encodings, however, such as 'utf8'
and 'latin1'
. Since the character values 0xF0-0xFF are used for telnet commands, not all characters for many encodings can be properly conveyed. 'utf8'
can work, however, for the roughly 64K characters in Unicode Basic Multilingual Plane (BMP).Resolves once the connection is ready (analogous to the ready
event).
Rejects if the timeout is hit.
Sends data on the socket (should be a compatible remote host's command if sane information is wanted).
The optional callback parameter will be executed with an error and response when the command is finally written out and the response data has been received.
If there was no error when executing the command, 'error' as the first argument to the callback will be undefined.
Command result will be passed as the second argument to the callback.
*** Important notice/API change from 0.3.0 *** The callback argument is now called with a signature of (error, [response])
Options:
shellPrompt
: Shell prompt that the host is using. Can be a string or an instance of RegExp. Defaults to regex /(?:\/ )?#\s/
.loginPrompt
: Username/login prompt that the host is using. Can be a string or an instance of RegExp. Defaults to regex /login[: ]*$/i
.failedLoginMatch
: String or regex to match if your host provides login failure messages. Defaults to undefined.timeout
: Sets the socket to timeout after the specified number of milliseconds
of inactivity on the socket.execTimeout
: A timeout used to wait for a server reply when this method is used. Defaults to 'undefined'.maxBufferLength
: Maximum buffer length in bytes which can be filled with response data. Defaults to 1M.irs
: Input record separator. A separator used to distinguish between lines of the response. Defaults to '\r\n'
.ors
: Output record separator. A separator used to execute commands (break lines on input). Defaults to '\n'
.echoLines
: The number of lines used to cut off the response. Defaults to 1. With a value of 0, no lines are cut off.Sends data on the socket without requiring telnet negotiations.
Options:
shellPrompt
: Shell prompt that the host is using. Can be a string or an instance of RegExp. Defaults to regex /(?:\/ )?#\s/
. Use negotiationMandatory: false
if you don't need this.shellPrompt
to null
if you wish to use the send(…)
or write(…)
methods, ignoring the returned values, and instead relying on nextData()
or on('data'…
for feedback.ors
: Output record separator. A separator used to execute commands (break lines on input). Defaults to '\n'.waitFor
: Wait for the given string or RegExp before returning a response. If not defined, the timeout value will be used.timeout
: A timeout used to wait for a server reply when the 'send' method is used. Defaults to 2000 (ms) or to sendTimeout ('connect' method) if set.maxBufferLength
: Maximum buffer length in bytes which can be filled with response data. Defaults to 1M.Same as send(…)
, but data
is sent without appending an output record separator.
Waits for and returns the next available data from the host, as a string value, either one line at a time, or the last-sent incomplete line. When the telnet session has ended, nextData()
always returns a Promise that resolves to null
.
Starts an interactive shell session. Returns a duplex stream which can be used to read and write data.
Returns a duplex stream that can be used for connection hopping. See 'sock' option.
Half-closes the socket. i.e., it sends a FIN packet. It is possible the server will still send some data.
Ensures that no more I/O activity happens on this socket. Only necessary in case of errors (parse error or so).
Emitted when a socket connection is successfully established.
Emitted when a socket connection is successfully established and the client is successfully connected to the specified remote host. A value of prompt is passed as the first argument to the callback.
Emitted when a write operation for given data is sent to the socket.
This is a forwarded 'data' event from core 'net' library. A <buffer>
is received when this event is triggered.
Emitted if the socket times out from inactivity. This is only to notify that the socket has been idle. The user must manually close the connection.
Emitted when the failedLoginMatch pattern is provided and a match is found from the host. The 'destroy()' method is called directly following this event.
Emitted when an error occurs. The 'close' event will be called directly following this event.
Emitted when the other end of the socket (remote host) sends a FIN packet.
Emitted once the socket is fully closed.
I offer professional support for node-telnet-client and beyond. I have many years of expertise on building robust, scalable Node.js applications and can help you overcome issues and challenges preventing you to ship your great products. I also excel in software architecture and implementation, being able to provide you with development, planning, consulting, training and customization services. Feel free to contact me so we can discuss how to help you finish your products!
Become a sponsor and get your logo on project's README on GitHub with a link to your site. Feel free to contact me for the arrangement!
If you love this project, consider donating!
This library is licensed under LGPLv3. Please see LICENSE for licensing details.
FAQs
A simple node.js telnet client
The npm package telnet-client receives a total of 256,425 weekly downloads. As such, telnet-client popularity was classified as popular.
We found that telnet-client demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.