|
| 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