Skip to content

Commit 5e66513

Browse files
committed
Complete port-sniffer homework
1 parent e6279e2 commit 5e66513

1 file changed

Lines changed: 129 additions & 0 deletions

File tree

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

0 commit comments

Comments
 (0)