Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions submissions/Vitamin/port-sniffer/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const help = `
Usage: sniffer.js [--help] [--ports <number>-<number>] [--host <value>]

These are commands used in sniffer application:

host Host address, IP or URL.
Examples: --host ukr.net,
--host 172.217.3.110

ports Ports range. Numbers must be more than 0 and less than 65535.
Examples: --port 30-562,
--port 1-65535.

help Show all commands.
`;

const isDefined = value => value != null && value !== false;

module.exports = { help, isDefined };
100 changes: 100 additions & 0 deletions submissions/Vitamin/port-sniffer/sniffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const Net = require('net');
const dns = require('dns').promises;
const { help, isDefined } = require('./helpers');

const [, , ...processArgs] = process.argv;
const [minPortValue, maxPortValue] = [0, 65535];

const ipToURL = async host => {
Comment thread
Vitaminvp marked this conversation as resolved.
Outdated
try {
const result = await dns.lookup(host);
return await result.address;
Comment thread
Vitaminvp marked this conversation as resolved.
Outdated
} catch (err) {
throw Error('Invalid host');
}
};

const isPortInRange = port => port >= minPortValue && port <= maxPortValue;

const getPortsRange = ports => {
const [firstPort, last] = ports.split('-');
const lastPort = isPortInRange(last) ? last : firstPort;
if (isPortInRange(firstPort)) {
return [firstPort, lastPort];
}
// eslint-disable-next-line no-console
console.log('Invalid ports range');
return undefined;
Comment thread
Vitaminvp marked this conversation as resolved.
Outdated
};

const tryToConnect = (host, port) => {
const client = new Net.Socket();
client.setTimeout(300);
client.connect({ port, host });
return new Promise(resolve => {
client.on('connect', () => {
process.stdout.write('.');
client.destroy();
return resolve(port);
});
client.on('timeout', () => {
client.destroy();
return resolve(false);
Comment thread
Vitaminvp marked this conversation as resolved.
Outdated
});
client.on('error', () => {
client.destroy();
return resolve(false);
});
});
};

const getOpenedPorts = async ({ host, firstPort, lastPort }) => {
const promises = [];
// eslint-disable-next-line no-plusplus
for (let i = firstPort; i <= lastPort; i++) {
promises.push(tryToConnect(host, i));
}
const ports = await Promise.all(promises);
return ports.filter(isDefined);
};

const parseArguments = async args => {
if (args.includes('--help')) {
// eslint-disable-next-line no-console
Comment thread
Vitaminvp marked this conversation as resolved.
Outdated
console.log(help);
process.exit(0);
} else if (
args.length < 4 ||
!args.includes('--ports') ||
!args.includes('--host')
) {
// eslint-disable-next-line no-console
console.log('Use --help to correct input');
process.exit(1);
}
const [firstPort, lastPort] = getPortsRange(args[1]);
const host = await ipToURL(args[3]);
return { host, firstPort, lastPort };
};

const getMessageToLog = openPorts => {
let result;
if (openPorts.length > 1) {
result = `\n${openPorts} ports are opened`;
} else if (openPorts.length === 1) {
result = `\n${openPorts} port is opened`;
} else {
result = '\nAll ports in range are closed';
}
return result;
};

const sniff = async args => {
const { host, firstPort, lastPort } = await parseArguments(args);
return getOpenedPorts({ host, firstPort, lastPort });
};

sniff(processArgs)
.then(getMessageToLog)
// eslint-disable-next-line no-console
.then(console.log);