Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
26 changes: 26 additions & 0 deletions submissions/Vitamin/port-sniffer/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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 compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
Comment thread
Vitaminvp marked this conversation as resolved.
Outdated

const composeAsync = (...fns) => async x => {
let res = x;
for (const fn of fns) {
res = await fn(res);
}
return res;
};

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

const [, , ...arguments] = 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];
} else {
console.log("Invalid ports range");
process.exit(1);
}
};

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 = [];
for (let i = firstPort; i <= lastPort; i++) {
promises.push(tryToConnect(host, i));
}
const ports = await Promise.all(promises);
return ports.filter(Boolean);
Comment thread
Vitaminvp marked this conversation as resolved.
Outdated
};

parseArguments = async args => {
Comment thread
Vitaminvp marked this conversation as resolved.
Outdated
if (args.includes("--help")) {
console.log(help);
process.exit(0);
} else if (
args.length < 4 ||
!args.includes("--ports") ||
!args.includes("--host")
) {
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 => {
if (openPorts.length > 1) return `\n${openPorts} ports are opened`;
else if (openPorts.length === 1) return `\n${openPorts} port is opened`;
return "\nAll ports in range are closed";
};

const sniffing = async args => {
Comment thread
Vitaminvp marked this conversation as resolved.
Outdated
const { host, firstPort, lastPort } = await parseArguments(args);
return await getOpenedPorts({ host, firstPort, lastPort });
Comment thread
Vitaminvp marked this conversation as resolved.
Outdated
};

sniffing(arguments)
.then(getMessageToLog)
.then(console.log);