Skip to content

Commit 97fb89e

Browse files
committed
Complete port-sniffer homework
1 parent e6279e2 commit 97fb89e

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
const net = require('net');
2+
3+
function getParamsFromArguments () {
4+
if (process.argv.includes('--help')) {
5+
showHelp();
6+
process.exit(0);
7+
}
8+
if (!process.argv.includes('--host')) {
9+
process.stdout.write('--host is required');
10+
process.exit(1);
11+
}
12+
return process.argv
13+
.slice(2)
14+
.join(' ')
15+
.split(/\s?--/)
16+
.reduce(function (acc, str) {
17+
if (!str) return acc;
18+
const [key, value] = str.split(' ');
19+
switch (key) {
20+
case 'help':
21+
break;
22+
case 'host':
23+
if (!value) {
24+
process.stdout.write('Host value must be provided, e.g. "--host 8.8.8.8"');
25+
process.exit(1);
26+
}
27+
acc[key] = value;
28+
break;
29+
case 'ports':
30+
if (!value) {
31+
process.stdout.write('Ports value must be provided, e.g. "--ports 300-1024"');
32+
process.exit(1);
33+
}
34+
if (!value.includes('-')) {
35+
process.stdout.write('Ports format invalid, must be e.g. "--ports 300-1024"');
36+
process.exit(1);
37+
} else {
38+
const [startPort, endPort] = value.split('-').map(port => parseInt(port, 10));
39+
if (isNaN(startPort) || startPort < 0) {
40+
process.stdout.write('Start port format invalid');
41+
process.exit(1);
42+
}
43+
if (isNaN(endPort) || endPort < 0) {
44+
process.stdout.write('End port format invalid');
45+
process.exit(1);
46+
}
47+
if (endPort > 65535) {
48+
process.stdout.write('End port must be between 0-65535');
49+
process.exit(1);
50+
}
51+
if (startPort > endPort) {
52+
process.stdout.write('End port must be bigger then start port');
53+
process.exit(1);
54+
}
55+
acc.startPort = startPort;
56+
acc.endPort = endPort;
57+
}
58+
break;
59+
default:
60+
acc[key] = value;
61+
}
62+
return acc;
63+
}, {});
64+
}
65+
66+
function showHelp () {
67+
console.log(`NAME
68+
TCP sniffer - scans open ports on specific host.
69+
70+
OPTIONS
71+
--help
72+
Output a usage message and exit.
73+
74+
--host
75+
Set a host for scan.
76+
E.g. "--host 127.0.0.1".
77+
78+
--ports
79+
Set ports to scan.
80+
E.g. "--ports 300-1024".
81+
Default values: 0-65535.
82+
83+
EXAMPLES
84+
node sniffer.js --host localhost
85+
node sniffer.js --host localhost --ports 300-1024
86+
`);
87+
}
88+
89+
function sniffConnectionAvailabilityAsync (port, host) {
90+
return new Promise(function (resolve, reject) {
91+
const socket = new net.Socket();
92+
socket.setTimeout(300);
93+
94+
socket.on('connect', function () {
95+
socket.destroy();
96+
resolve();
97+
});
98+
socket.on('timeout', function () {
99+
socket.destroy();
100+
reject(new Error('timeout'));
101+
});
102+
socket.on('error', function (err) {
103+
socket.destroy();
104+
reject(err);
105+
});
106+
107+
socket.connect(port, host);
108+
});
109+
}
110+
111+
async function scanAsync (host, port, portLimit, availablePorts = []) {
112+
if (port > portLimit) {
113+
return availablePorts;
114+
}
115+
try {
116+
await sniffConnectionAvailabilityAsync(port, host);
117+
process.stdout.write('.');
118+
availablePorts.push(port);
119+
} catch (e) {}
120+
return scanAsync(host, port + 1, portLimit, availablePorts);
121+
}
122+
123+
(async function () {
124+
const { host, startPort = 0, endPort = 65535 } = getParamsFromArguments();
125+
const openedPorts = await scanAsync(host, startPort, endPort);
126+
const result = openedPorts.length ? `\n${openedPorts.join(',')} ports are opened` : `\nNo open ports on host: ${host}`;
127+
process.stdout.write(result);
128+
process.exit(0);
129+
})();

0 commit comments

Comments
 (0)