2016-04-23 3 views
0

Ich versuche, ein einfaches Portscan-Skript in Nodejs zu schreiben. Sie können dieses Skript gegen scanme.nmap.org ausführen. Durch die Ausführung nmap selbst weiß ich, dass dieser Host vier offene Ports: 22, 80, 9929, 31337.Portscan in Knoten funktioniert nicht, wenn der Portbereich zu breit ist

Mein Skript ist:

var net = require('net'); 
var host = 'scanme.nmap.org'; 
var max = 35000; 

function scanPort(port) { 
    try { 
     var c = new net.Socket(); 
     c.setTimeout(5000); 
     c.connect({ 
      port: port, 
      host: host 
     }) 

     c.on('connect', function() { 
      console.log(port); 
     }) 

     c.on('error', function (err) { 
      c.destroy(); 
     }) 

     c.on('timeout', function() { 
      c.destroy(); 
     }) 
    } catch (err) { 
     console.error(err); 
    } 
} 

for (i = 1; i<=max; i++) { 
    scanPort(i); 
} 

Wenn ich die Schleife von i = 1 starten, wird das Skript Ports erkennen 22 und 80, danach wird es mit dem Exit-Code 0 verlassen. Es wird die anderen zwei Ports nicht erkennen. Wenn ich mit der Variablen i spiele, d. H. Die ersten Ports überspringe und i = 9500 setze, wird Port 9929 korrekt erkannt. Gleiches passiert, wenn ich i = 31000 setze, wird Port 31337 erkannt.

Ich verstehe nicht wirklich, warum es nicht wie erwartet funktioniert. Ich vermute ein Systemlimit verursacht einige Fehler, aber ich habe versucht, die Scan-Funktion in einen try Block zu wickeln, konnte aber keinen Fehler feststellen.

+0

Fügen Sie eine console.log in den Fehler und Timeout-Rückruf hinzu. Versuchen Sie, fangen Sie nicht Hilfe in asynchronen Code. –

+0

Sie sollten wahrscheinlich die maximale Anzahl der geöffneten Dateideskriptoren erhöhen. Dies ist abhängig vom Betriebssystem. – lipp

Antwort

4

Sie versuchen wahrscheinlich, zu viele Verbindungen auf einmal zu öffnen und keine Ressourcen mehr zu haben oder auf dem empfangenden Server blockiert zu werden, um ihn zu überfluten.

Da all Ihre Socket-Dateien asynchron sind, versucht Ihre for-Schleife sofort, 35.000 Sockets zu öffnen. Während Server dafür konfiguriert werden können, erfordert es eine sehr spezielle Konfiguration und es braucht ein wenig Speicherschema für die Verwendung jedes Sockets (das Sie hier nicht haben).

So eine einfache Lösung ist es, zu begrenzen, wie viele Sockets auf einmal zu einer vernünftigen Anzahl geöffnet sind.

Hier ist ein Code, der anfänglich eine feste Anzahl von Sockets öffnet und dann, wenn jeder abgeschlossen ist, öffnet er einen anderen, der eine feste Anzahl von offenen und aktiven Sockets beibehält. Es ist derzeit so eingestellt, dass 100 Sockets gleichzeitig geöffnet sind. Sie können in Ihrer Umgebung und das Betriebssystem experimentieren, um zu sehen, wie hoch Sie diese Zahl ohne anfallenden Probleme machen kann:

var net = require('net'); 
var host = 'scanme.nmap.org'; 
var low = 1; 
var high = 35000; 

var maxInFlight = 100; 


function scanPort(port) { 
    return new Promise(function(resolve, reject) { 
     var c = new net.Socket(); 
     c.setTimeout(5000); 
     c.connect({ 
      port: port, 
      host: host 
     }) 

     c.on('connect', function() { 
      console.log(port); 
      c.destroy(); 
      resolve(port); 
     }) 

     c.on('error', function (err) { 
      c.destroy(); 
      reject(err); 
     }) 

     c.on('timeout', function() { 
      c.destroy(); 
      reject({code: "Timeout", port: port}); 
     }) 
    }); 
} 

var cntr = low; 
var inFlightCnt = 0; 

function run() { 
    while (inFlightCnt < maxInFlight && cntr <= high) { 
     ++inFlightCnt; 
     scanPort(cntr++).then(function(port) { 
      --inFlightCnt; 
      run(); 
     }, function(err) { 
      --inFlightCnt; 
      run(); 
     }); 
    } 
} 

run(); 

Hinweis: Wenn für 100 zu einer Zeit eingestellt, dies dauert eine Weile, bis alle Ports laufen zu 35.000. Es findet die vier offenen Ports, die Sie erwähnen.


Und hier ist eine andere Version, die Informationen über jeden Port sammelt und wie es ausgefallen/gelungen, so dass Sie am Ende einen Dump erhalten. Es zeigt auch die Fortschritte in der Konsole, so können Sie sehen, ob es noch läuft oder nicht und wie nahe sie getan wird:

var net = require('net'); 
var host = 'scanme.nmap.org'; 

var low = 1; 
var high = 35000; 

var maxInFlight = 200; 


function scanPort(port) { 
    return new Promise(function(resolve, reject) { 
     var c = new net.Socket(); 
     c.setTimeout(15000); 
     c.connect({ 
      port: port, 
      host: host 
     }) 

     c.on('connect', function() { 
      c.destroy(); 
      resolve(port); 
     }) 

     c.on('error', function (err) { 
      c.destroy(); 
      reject(err); 
     }) 

     c.on('timeout', function() { 
      c.destroy(); 
      reject({code: "timeout", port: port}); 
     }) 
    }); 
} 

var cntr = low; 
var inFlightCnt = 0; 

var openPorts = []; 
var timeouts = []; 
var refused = []; 
var otherErrors = []; 

function run() { 
    while (inFlightCnt < maxInFlight && cntr <= high) { 
     ++inFlightCnt; 
     scanPort(cntr++).then(function(port) { 
      --inFlightCnt; 
      openPorts.push(port); 
      console.log(openPorts); 
      run(); 
     }, function(err) { 
      if (err.code === "timeout" || err.code === "ETIMEDOUT") { 
       timeouts.push(err.port); 
      } else if (err.code === "ECONNREFUSED") { 
       refused.push(err.port); 
      } else { 
       otherErrors.push(err.port); 
      } 
      console.log(err.code + ": " + err.port); 
      --inFlightCnt; 
      run(); 
     }); 
    } 
    // if we are all done here, log the open ports 
    if (inFlightCnt === 0 && cntr >= high) { 
     console.log("open: " + JSON.stringify(openPorts)); 
     console.log("timeouts: " + JSON.stringify(timeouts)); 
     console.log("otherErrors: " + JSON.stringify(otherErrors)); 
    } 
} 

run(); 

Hier ist die Ausgabe, die es erzeugt, wenn ich es auf Windows 10 mit Knoten v4.0.0 laufen :

open: [22,80,9929,31337] 
timeouts: [25,135,136,137,138,139,445,974,984,972,965,963,964,978,985,980,975,981,987,971,960,977,1000,992,990,986,991,997,1391,1384,7455,7459,7450,7506,7512,23033,23736,33635,33640,33638,33641,33634,33636,33633] 
otherErrors: [] 

Ich weiß nicht, warum einige Häfen auslaufen. Die meisten bekommen ECONNREFUSED, was eine Art von was Sie erwarten würden für einen Port, der nicht geöffnet ist, einige erhalten ETIMEDOUT aus der Bibliothek net und ein paar Timeout von der Zeitüberschreitung in Ihrem Code (die ich auf 15 Sekunden erhöht).

Beachten Sie auch, dass ich eine Zerstörung hinzugefügt habe, nachdem sie verbinden. Sie haben diese Steckdosen offen gelassen, was hier funktioniert, wenn nur ein paar verbinden, aber könnte ein Problem sein, wenn viele Anschlüsse verbinden.


zur Vorsicht: Während dieses Programm Testen lief ich es viele, viele Male und nach ca. 20. Mal, dass ich es lief meine Internet-Verbindung ging eine Weile nach unten und es dauerte einen Neustart meines Kabel Modem, damit die Dinge wieder funktionieren. Ich vermute, dass etwas im Inneren des Kabelmodems während des Testens nicht mit dieser schnellen Flut von Anfragen fertig wird. Es könnte aber auch sein, dass Comcast wegen der ungewöhnlichen Aktivität (eine Flut von Port-Anfragen) meine Verbindung beendet hat.

Natürlich könnte dies alles ein Zufall gewesen sein und mein kleiner Ausfall hätte keine Verbindung zu dem haben können, was ich tat, aber das Timing scheint zu verbunden zu sein, um zu denken, dass es nur ein Zufall ist.

Dieses Programm könnte weiter modifiziert werden, um es zu "verlangsamen", indem nicht mehr als N Port-Sonden pro Sekunde gemessen werden.

+0

Es wurde eine neue Version des Codes hinzugefügt, der Daten für jeden Socket sammelt. Am Ende sehen Sie eine Zusammenfassung. – jfriend00

Verwandte Themen