Skip to content

Commit 518e887

Browse files
port-sniffer is developed
1 parent c5297f3 commit 518e887

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

submissions/amashoshyna/port-sniffer/index.js

Whitespace-only changes.
File renamed without changes.
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
const dns = require('dns');
2+
const { Socket } = require('net');
3+
4+
const defaultPortLimits = {
5+
startPort: 0,
6+
endPort: 65535
7+
};
8+
const timeout = 300;
9+
10+
const helpMessage = `Sniffer params usage:
11+
--host - required argument which can be either domain name, like google.com or IP address like 172.217.3.110
12+
--ports - limits range of ports to scan, should be provided in format (start_port)-(end_port), for instance: 3-600
13+
--help - flag to see hint about how to use TCP sniffer\n`;
14+
const hostErrorMessage = `--host parameter with its value should be passed\n`;
15+
const portsErrorMessage = `--ports value should be passed as a port range with limits(0-65535), like 15-333\n`;
16+
function lookupErrorMessage(error) {
17+
return `Error ${error.code} occurred during ${error.syscall} call for '${error.hostname}' host\n`;
18+
}
19+
20+
function stdoutWrite(str) {
21+
process.stdout.write(str);
22+
}
23+
24+
function exit(code) {
25+
process.exit(code);
26+
}
27+
28+
function parseArgs(args) {
29+
if (args.includes('--help')) {
30+
stdoutWrite(helpMessage);
31+
exit(0);
32+
} else if (
33+
args.indexOf('--host') === -1 ||
34+
!args[args.indexOf('--host') + 1]
35+
) {
36+
stdoutWrite(hostErrorMessage);
37+
exit(1);
38+
}
39+
40+
return args.reduce((result, item, index, arr) => {
41+
if (item.indexOf('--') === 0 && arr[index + 1]) {
42+
return { ...result, [item]: arr[index + 1] };
43+
}
44+
return result;
45+
}, {});
46+
}
47+
48+
async function getAddress(host) {
49+
return new Promise((resolve, reject) => {
50+
dns.lookup(host, (err, address) => {
51+
if (err) reject(err);
52+
resolve(address);
53+
});
54+
}).catch(e => {
55+
stdoutWrite(lookupErrorMessage(e));
56+
exit(1);
57+
});
58+
}
59+
60+
function getPortLimits(portsRange) {
61+
const arePortsValid = ports =>
62+
ports.length === 2 &&
63+
ports[0] >= defaultPortLimits.startPort &&
64+
ports[1] > ports[0] &&
65+
ports[1] <= defaultPortLimits.endPort;
66+
67+
const portArr = portsRange.split('-').map(portNum => parseInt(portNum, 10));
68+
69+
if (!arePortsValid(portArr)) {
70+
stdoutWrite(portsErrorMessage);
71+
exit(1);
72+
}
73+
return { startPort: portArr[0], endPort: portArr[1] };
74+
}
75+
76+
async function scanAddressPort(address, port) {
77+
return new Promise(resolve => {
78+
const socket = new Socket();
79+
socket.setTimeout(timeout);
80+
81+
socket.on('connect', () => {
82+
stdoutWrite('.');
83+
resolve(port);
84+
socket.destroy();
85+
});
86+
87+
socket.on('timeout', () => {
88+
resolve(false);
89+
socket.destroy();
90+
});
91+
92+
socket.on('error', () => {
93+
resolve(false);
94+
socket.destroy();
95+
});
96+
97+
socket.connect(port, address);
98+
});
99+
}
100+
101+
function getAddressOpenPorts(address, startPort, endPort) {
102+
const openPorts = [];
103+
for (let port = startPort; port < endPort; port += 1) {
104+
openPorts.push(scanAddressPort(address, port));
105+
}
106+
return Promise.all(openPorts).then(values => values.filter(Number.isFinite));
107+
}
108+
109+
(async function sniff() {
110+
const processArgs = process.argv.slice(2);
111+
const parsedArgs = parseArgs(processArgs);
112+
const address = await getAddress(parsedArgs['--host']);
113+
const portLimits =
114+
'--ports' in parsedArgs
115+
? getPortLimits(parsedArgs['--ports'])
116+
: defaultPortLimits;
117+
const openPorts = await getAddressOpenPorts(
118+
address,
119+
portLimits.startPort,
120+
portLimits.endPort
121+
);
122+
if (openPorts.length > 0) {
123+
stdoutWrite(`\n${openPorts.join(', ')} ports are opened\n`);
124+
} else {
125+
stdoutWrite('No opened ports\n');
126+
}
127+
exit(0);
128+
})();

0 commit comments

Comments
 (0)