Timing und Performance

Bei der Entwicklung von Nmap hatte dessen Performance immer eine der höchsten Prioritäten. Ein Standardscan (nmap <hostname>) eines Hosts in meinem lokalen Netzwerk dauert eine Fünftelsekunde. In dieser Zeit kann man kaum blinzeln, aber wenn man Hunderte oder Tausende von Rechnern scannt, dann kommt einiges zusammen. Außerdem können bestimmte Scan-Optionen wie UDP-Scanning und eine Versionserkennung die Scan-Zeiten erheblich erhöhen. Das Gleiche gilt für bestimmte Firewall-Konfigurationen und besonders für die Beschränkung der Antwortrate. Auch wenn Nmap parallel arbeitet und viele ausgefeilte Algorithmen benutzt, um diese Scans zu beschleunigen, hat doch der Benutzer die letzte Kontrolle darüber, was Nmap genau macht. Experten erstellen ihre Nmap-Befehle sehr sorgfältig, um in einer beschränkten Zeit genau die gewünschte Information zu bekommen.

Um die Scan-Zeiten zu verbessern, kann man z.B. nicht-kritische Tests weglassen und auf die neueste Version von Nmap aktualisieren (Performance-Verbesserungen werden häufig gemacht). Auch die Optimierung von Timing-Parametern kann einen großen Unterschied ausmachen. Diese Optionen werden im Folgenden beschrieben.

Manche Optionen erwarten einen time-Parameter. Dieser wird standardmäßig in Millisekunden angegeben, aber Sie können ‘s’, ‘m’ oder ‘h’ an den Wert anhängen, um Sekunden, Minuten oder Stunden anzugeben. Das heißt, bei --host-timeout haben die Argumente 900000, 900s und 15m alle denselben Effekt.

--min-hostgroup <numhosts>; --max-hostgroup <numhosts> (Größe der parallel gescannten Gruppen anpassen)

Nmap hat die Fähigkeit, Port-Scans oder Versions-Scans von mehreren Hosts parallel durchzuführen. Das macht Nmap, indem es den Ziel-IP-Adressraum in Gruppen aufteilt und dann jeweils eine Gruppe scannt. Im Allgemeinen sind größere Gruppen effizienter. Der Nachteil daran ist, dass die Host-Ergebnisse erst dann ausgegeben werden können, wenn die gesamte Gruppe fertig ist. Wenn Nmap mit einer Gruppengröße von 50 anfängt, würde der Benutzer erst dann Ergebnisse sehen (bis auf die Aktualisierungen im ausführlichen Modus), wenn die ersten 50 Hosts abgearbeitet sind.

Diesen Konflikt löst Nmap standardmäßig mit einem Kompromissansatz. Es fängt mit einer kleinen Gruppengröße von etwa fünf an, damit die ersten Ergebnisse schnell kommen, und erhöht dann die Gruppengröße bis auf etwa 1024. Die genau vorgegebenen Zahlen hängen von den benutzten Optionen ab. Aus Effizienzgründen benutzt Nmap größere Gruppen bei UDP-Scans oder bei TCP-Scans über wenige Ports.

Falls mit --max-hostgroup eine maximale Gruppengröße angegeben wird, wird Nmap diese nie überschreiten. Und wenn Sie mit --min-hostgroup eine minimale Größe angeben, versucht Nmap, die Gruppengröße oberhalb dieses Wertes zu belassen. Falls es auf einer gegebenen Schnittstelle nicht genug Zielhosts gibt, um dieses Minimum zu erfüllen, muss Nmap einen kleineren Wert benutzen. Es können auch beide gesetzt werden, um die Gruppengröße in einem bestimmten Bereich zu belassen, aber das ist selten gewünscht.

Diese Optionen haben während der Host-Entdeckungsphase eines Scans keinen Effekt. Dazu gehören einfache Ping-Scans (-sP). Die Host-Entdeckung funktioniert immer in großen Gruppen von Hosts, um die Geschwindigkeit und Genauigkeit zu verbessern.

Der Hauptnutzen dieser Optionen liegt darin, eine hohe minimale Gruppengröße anzugeben, damit der gesamte Scan schneller läuft. Häufig wird 256 gewählt, um ein Netzwerk in Brocken der Größe von Klasse C zu scannen. Bei einem Scan mit vielen Ports bringt eine größere Zahl vermutlich keine Vorteile. Bei Scans über nur wenige Ports können Gruppengrößen von 2048 oder mehr hilfreich sein.

--min-parallelism <numprobes>; --max-parallelism <numprobes> (Parallelität von Testpaketen anpassen)

Diese Optionen steuern die Gesamtanzahl an Testpaketen, die für eine Host-Gruppe anstehen dürfen. Sie werden beim Port-Scanning und bei der Host-Entdeckung benutzt. Abhängig von der Netzwerk-Performance berechnet Nmap standardmäßig eine immer wechselnde ideale Parallelität. Falls Pakete verworfen werden, verlangsamt sich Nmap und erlaubt weniger unerledigte Testpakete. Die ideale Anzahl von Testpaketen steigt mit den zunehmenden Möglichkeiten des Netzwerks. Diese Optionen setzen minimale oder maximale Schranken für diese Variable. Standardmäßig kann die ideale Parallelität auf eins sinken, wenn sich das Netzwerk als unzuverlässig herausstellt, und im Idealfall kann sie auf mehrere hundert steigen.

Meistens setzt man --min-parallelism auf eine Zahl größer als eins, um Scans von langsamen Hosts oder Netzwerken zu beschleunigen. Aber das Spielen mit dieser Option kann gefährlich sein, weil die Genaugkeit leiden kann, wenn man einen zu großen Wert setzt. Dabei verringert sich auch Nmaps Möglichkeit, die Parallelität je nach Netzwerkbedingungen dynamisch anzupassen. Ein Wert von zehn mag vernünftig sein, auch wenn ich nur als letzter Ausweg an diesem Wert drehe.

Die Option --max-parallelism wird manchmal auf eins gesetzt, um zu verhindern, dass Nmap mehr als ein Testpaket auf einmal an Hosts sendet. In Kombination mit --scan-delay (wird später behandelt) kann das nützlich sein, auch wenn Letzteres diesen Zweck gut genug allein erfüllt.

--min-rtt-timeout <time>, --max-rtt-timeout <time>, --initial-rtt-timeout <time> (Timeouts von Testpaketen anpassen)

Nmap verwaltet einen laufenden Timeout-Wert, der bestimmt, wie lange es auf eine Antwort zu einem Testpaket wartet, bevor es aufgibt oder das Paket erneut sendet. Dieser wird auf der Grundlage der Antwortzeiten bei früheren Testpaketen berechnet. Falls die Netzwerk-Latenzzeit sich als groß genug und variabel erweist, kann dieser Timeout bis auf mehrere Sekunden wachsen. Er beginnt auch bei einem konservativen (hohen) Wert und kann diesen eine Weile behalten, wenn Nmap Hosts scannt, die nicht antworten.

Werden Werte für --max-rtt-timeout und --initial-rtt-timeout angegeben, die kleiner als deren Standardwerte sind, so kann die Scan-Zeit erheblich verkürzt werden. Das gilt besonders für pinglose (-PN) Scans und solche von stark gefilterten Netzwerken. Aber verlangen Sie nicht zu viel. Der Scan kann am Ende länger brauchen, wenn Sie einen so kleinen Wert angeben, dass bei vielen Testpaketen der Timeout erreicht wird und sie erneut gesendet werden, während die Antwort unterwegs ist.

Falls alle Hosts in einem lokalen Netzwerk sind, sind 100 Millisekunden ein vernünftig aggressiver Wert für --max-rtt-timeout. Falls ein Routing ins Spiel kommt, pingen Sie zuerst einen Host im Netzwerk, sei es mit einem ICMP-Ping oder mit einem Programm zur Erstellung benutzerdefinierter Pakete wie hping2, das eine höhere Chance hat, durch eine Firewall zu kommen. Betrachten Sie dann die maximale Umlaufzeit bei circa zehn Paketen. Diese möchten Sie vielleicht für --initial-rtt-timeout verdoppeln und für --max-rtt-timeout verdrei- oder vervierfachen. Im Allgemeinen setze ich die maximale RTT nicht unter 100 ms, egal, welche Ping-Zeiten ich habe. Und ich gehe auch nicht über 1000 ms.

Die Option --min-rtt-timeout wird selten benutzt, könnte aber nützlich sein, wenn ein Netzwerk so unzuverlässig ist, dass selbst Nmaps Standardeinstellung zu aggressiv ist. Da Nmap das Timeout nur dann auf das Minimum reduziert, wenn das Netzwerk zuverlässig scheint, sollte ein Bedarf hierfür eher ungewöhnlich sein und sollte als Fehler auf der nmap-dev-Mailingliste berichtet werden.

--max-retries <numtries> (gibt die maximale Anzahl erneuter Sendeversuche bei Port-Scan-Testpaketen an)

Falls Nmap keine Antwort auf ein Testpaket eines Port-Scans erhält, könnte das heißen, dass der Port gefiltert ist. Oder aber das Testpaket oder die Antwort darauf ging im Netzwerk verloren. Es ist auch möglich, dass der Zielhost eine Ratenbeschränkung aktiviert hat, die die Antwort temporär blockiert hat. Also versucht es Nmap erneut, indem es das ursprüngliche Paket noch einmal sendet. Falls Nmap eine mangelnde Netzwerkzuverlässigkeit feststellt, führt es eventuell viele weitere Wiederholungen durch, bevor es bei einem Port aufgibt. Das verbessert zwar die Genauigkeit, verlängert aber auch die Scan-Zeiten. Wenn es auf die Performance ankommt, kann man die Scans durch eine Beschränkung der Anzahl dieser Wiederholungen beschleunigen. Sie können sogar --max-retries 0 angeben, um sie ganz zu verbieten, auch wenn sich das nur in Situationen wie formlosen Überprüfungen empfiehlt, bei denen einige verpasste Ports oder Hosts nicht so wichtig sind.

Der Standardwert (ohne -T-Template) sind bis zu zehn Wiederholungen. Falls das Netzwerk zuverlässig zu sein scheint und die Zielhosts keine Ratenbeschränkung haben, führt Nmap normalerweise nur eine Wiederholung durch. Daher sind die meisten Scans gar nicht betroffen, wenn man --max-retries z.B. auf den kleinen Wert drei verringert. Solche Werte können Scans von langsamen (ratenbeschränkten) Hosts aber erheblich beschleunigen. Wenn Nmap frühzeitig bei Ports aufgibt, verlieren Sie eventuell einiges an Information, aber das kann vorteilhafter sein, als ein Timeout von --host-timeout zu erreichen und alle Informationen über das Ziel zu verlieren.

--host-timeout <time> (bei langsamen Zielhosts aufgeben)

Bei manchen Hosts braucht es einfach lange, sie zu scannen. Das kann an leistungsschwacher oder unzuverlässiger Netzwerk-Hardware oder -Software, an einer Paketratenbeschränkung oder einer restriktiven Firewall liegen. Die langsamsten paar Prozent der gescannten Hosts können einen Großteil der Scan-Zeit verbrauchen. Dann ist es manchmal das Beste, die Verluste abzuschneiden und diese Hosts erst einmal wegzulassen. Geben Sie --host-timeout mit der gewünschten maximalen Wartezeit an. Sie können z.B. 30m angeben, um sicherzustellen, dass Nmap nicht mehr als eine halbe Stunde verschwendet, indem es auf einen einzelnen Host wartet. Beachten Sie, dass Nmap während dieser halben Stunde auch andere Hosts scannen kann, d.h. es ist keine komplette Zeitverschwendung. Ein Host, der das Timeout erreicht, wird übersprungen. Für diesen Host werden keine Ergebnisse der Port-Tabelle, Betriebssystem- oder Versionserkennung ausgegeben.

--scan-delay <time>; --max-scan-delay <time> (Verzögerung zwischen Testpaketen anpassen)

Diese Option bewirkt, dass Nmap mindestens die angegebene Zeit zwischen zwei Testpaketen an einen Host wartet. Das ist besonders bei einer Ratenbeschränkung sinnvoll. Solaris-Rechner (und viele andere auch) antworten auf UDP-Scan-Testpakete normalerweise nur mit einer ICMP-Nachricht pro Sekunde. Wenn Nmap mehr sendet, ist das Verschwendung. Mit einem --scan-delay von 1s bleibt Nmap bei dieser langsamen Rate. Nmap versucht eine Ratenbeschränkung zu erkennen und die Scan-Verzögerung entsprechend anzupassen, aber es schadet nicht, sie explizit anzugeben, falls Sie schon wissen, welche Rate am besten funktioniert.

Wenn Nmap die Scan-Verzögerung nach oben anpasst, um mit der Ratenbeschränkung klarzukommen, verlangsamt sich der Scan dramatisch. Die Option --max-scan-delay gibt die größte Verzögerung an, die Nmap erlaubt. Ein kleiner Wert für --max-scan-delay kann Nmap beschleunigen, ist aber riskant. Ein zu kleiner Wert kann zu verschwenderischen wiederholten Sendungen führen und möglicherweise zu verpassten Ports, wenn das Ziel eine strenge Ratenbeschränkung implementiert.

Ein weiterer Einsatz von --scan-delay liegt bei der Umgehung schwellwertbasierter Intrusion-Detection- und -Prevention-Systeme (IDS/IPS).

--min-rate <number>; --max-rate <number> (direkte Steuerung der Scan-Rate)

Nmaps dynamisches Timing findet sehr gut die passende Scan-Geschwindigkeit. Aber manchmal kennen Sie vielleicht die passende Scan-Rate für ein Netzwerk, oder vielleicht müssen Sie garantieren, dass ein Scan bis zu einem bestimmten Zeitpunkt fertig wird. Oder Sie müssen Nmap vielleicht davon abhalten, zu schnell zu scannen. Für diese Situationen sind die Optionen --min-rate und --max-rate vorgesehen.

Bei der Option --min-rate versucht Nmap sein Bestes, um Pakete so schnell wie die damit angegebene Rate zu senden oder noch schneller. Das Argument ist eine positive Fießkommazahl, die die Paketrate in Paketen pro Sekunde angibt. Die Angabe --min-rate 300 bedeutet z.B., dass Nmap eine Rate von 300 Paketen pro Sekunde oder höher einzuhalten versucht. Die Angabe einer Minimalrate hält Nmap nicht davon ab, bei günstigen Bedingungen schneller zu werden.

Umgekehrt beschränkt --max-rate die Senderate auf das angegebene Maximum. Bei --max-rate 100 wird sie auf 100 Pakete pro Sekunde bei einem schnellen Netzwerk beschränkt. Und bei --max-rate 0.1 wird der Scan auf ein Paket pro zehn Sekunden verlangsamt. Mit --min-rate und --max-rate gleichzeitig können Sie die Rate in einem bestimmten Bereich halten.

Diese beiden Optionen sind global und betreffen den gesamten Scan, nicht nur einzelne Hosts. Sie betreffen nur Port-Scans und Host-Entdeckungs-Scans. Andere Merkmale wie die Betriebssystemerkennung implementieren ihr eigenes Timing.

Unter zwei Bedingungen kann die tatsächliche Scan-Rate unter das verlangte Minimum fallen. Die erste ist, wenn das Minimum schneller als die schnellste Rate ist, mit der Nmap senden kann, was hardwareabhängig ist. In diesem Fall sendet Nmap Pakete einfach so schnell wie möglich, aber Sie sollten wissen, dass solch hohe Raten sehr wahrscheinlich einen Verlust an Genauigkeit bedeuten. Die zweite Bedingung ist, wenn Nmap nichts zu senden hat, z.B. am Ende eines Scans, nachdem die letzten Testpakete gesendet wurden und Nmap darauf wartet, dass sie einen Timeout verursachen oder beantwortet werden. Eine sinkende Scan-Rate am Ende eines Scans oder zwischen Gruppen von Hosts ist normal. Die Senderate kann temporär das Maximum übersteigen, um unvorhergesehene Verzögerungen auszugleichen, aber im Durchschnitt bleibt die Rate bei oder unter dem Maximum.

Eine minimale Rate sollte man mit Vorsicht angeben. Scans, die schneller sind, als das Netzwerk erlaubt, können zu einem Verlust von Genauigkeit führen. In manchen Fällen kann die Wahl eines schnelleren Scans dazu führen, dass er länger braucht als bei einer kleineren Rate. Das liegt daran, dass Nmaps Algorithmen für die adaptive retransmission die von einer zu hohen Scan-Rate verursachte Netzwerküberlastung erkennen und die Anzahl der Wiederholungen erhöhen, um die Genauigkeit zu verbessern. Das heißt, selbst wenn Pakete mit höherer Rate gesendet werden, werden mehr Pakete insgesamt gesendet. Begrenzen Sie diese Anzahl von Wiederholungen nach oben mit der Option --max-retries, wenn Sie eine obere Grenze für die gesamte Scan-Zeit setzen müssen.

--defeat-rst-ratelimit

Viele Hosts haben lange eine Ratenbeschränkung benutzt, um die Anzahl der von ihnen gesendeten ICMP-Fehlermeldungen (z.B. Port-Unreachable-Fehler) zu reduzieren. Manche Systeme wenden nun ähnliche Ratenbeschränkungen auf die von ihnen erzeugten RST-(Reset-)Pakete an. Das kann Nmap dramatisch verlangsamen, weil es sein Timing an diese Ratenbeschränkungen anpasst. Mit der Option --defeat-rst-ratelimit können Sie Nmap sagen, dass es diese Ratenbeschränkungen ignorieren soll (z.B. bei Port-Scans wie dem SYN-Scan, die nicht-antwortende Ports nicht als offen behandeln).

Diese Option kann die Genauigkeit reduzieren, da einige Ports nicht zu antworten scheinen, weil Nmap nicht lange genug auf eine ratenbeschränkte RST-Antwort gewartet hat. Bei einem SYN-Scan führt die ausbleibende Antwort dazu, dass für den Port der Zustand gefiltert und geschlossen markiert wird, den wir sehen, wenn RST-Pakete empfangen werden. Diese Option ist nützlich, wenn Sie sich nur für offene Ports interessieren und eine Unterscheidung zwischen geschlossenen und gefilterten Ports die zusätzliche Zeit nicht wert ist.

-T paranoid|sneaky|polite|normal|aggressive|insane (setzt ein Timing-Template)

Auch wenn die feinkörnigen Timing-Einstellungen im letzten Abschnitt mächtig und effektiv sind, finden manche Leute sie verwirrend. Außerdem kann die Wahl der passenden Werte manchmal mehr Zeit erfordern als der Scan, den Sie damit optimieren möchten. Deswegen bietet Nmap auch einen einfacheren Ansatz mit sechs Timing-Templates. Diese können Sie mit der Option -T und ihrer Nummer (0–5) oder mit ihrem Namen angeben. Diese Template-Namen lauten: paranoid (0), sneaky (1), polite (2), normal (3), aggressive (4) und insane (5). Die ersten beiden sind für die Umgehung von IDS gedacht. Der Polite-Modus verlangsamt den Scan, damit er weniger Bandbreite und Ressourcen auf dem Zielrechner verbraucht. Der Normal-Modus ist der Standardwert, d.h. -T3 macht gar nichts. Der Aggressive-Modus beschleunigt Scans, indem er davon ausgeht, dass Sie sich in einem einigermaßen schnellen und zuverlässigen Netzwerk befinden. Und schließlich geht der Insane-Modus davon aus, dass sie sich in einem außergewöhnlich schnellen Netzwerk befinden bzw. gewillt sind, für mehr Geschwindigkeit auf etwas Genauigkeit zu verzichten.

Mit diesen Templates können Benutzer angeben, wie aggressiv sie vorgehen möchten, und trotzdem Nmap die Wahl der genauen Zeitwerte überlassen. Diese Templates führen außerdem auch kleine Geschwindigkeitsanpassungen aus, für die es zur Zeit keine feinkörnigen Einstellungsoptionen gibt. Zum Beispiel verbietet -T4, dass die dynamische Scan-Verzögerung bei TCP-Ports über 10 ms ansteigt, und -T5 begrenzt diesen Wert auf 5 ms. Templates könen auch in Kombination mit feinkörnigen Einstellungen benutzt werden, wobei die feinkörnigeren Optionen die entsprechenden allgemeinen Werte aus den Templates überschreiben. Ich empfehle den Einsatz von -T4 beim Scannen halbwegs moderner und zuverlässiger Netzwerke. Wenn Sie diese Option angeben, auch dann, wenn Sie zusätzliche feinkörnige Einstellungen benutzen, profitieren Sie von den weiteren kleinen Optimierungen, die damit verbunden sind.

Falls Sie eine anständige Breitband- oder Ethernet-Verbindung haben, würde ich empfehlen, immer -T4 zu benutzen. Manche Leute lieben -T5, was für meinen Geschmack aber zu aggressiv ist. Manchmal geben Leute -T2 an, weil sie denken, dadurch würden Hosts weniger abstürzen, oder weil sie sich selbst im Allgemeinen für höflich halten. Oft realisieren sie einfach nicht, wie langsam -T polite tatsächlich ist. Ein solcher Scan kann zehnmal mehr Zeit benötigen als ein Standard-Scan. Rechnerabstürze und Bandbreitenprobleme kommen mit den standardmäßigen Timing-Optionen (-T3) selten vor, weswegen ich das normalerweise vorsichtigen Scannern empfehle. Auf die Versionserkennung zu verzichten ist weit wirksamer bei der Reduktion dieser Probleme als das Herumprobieren mit Zeiteinstellungen.

Zwar sind -T0 und -T1 vielleicht hilfreich bei der Vermeidung von IDS-Alarmen, benötigen aber außergewöhnlich viel Zeit beim Scannen von Tausenden von Rechnern oder Ports. Für einen derart langen Scan möchten Sie vielleicht doch lieber die genau benötigten Zeitwerte angeben, statt sich auf die vorgefertigten Werte von -T0 und -T1 zu verlassen.

Die Haupteffekte von T0 sind die Serialisierung des Scans, bei der immer nur ein Port gescannt wird, und eine Wartezeit von fünf Minuten zwischen zwei Testpaketen. T1 und T2 sind ähnlich, warten aber jeweils nur 15 bzw. 0,4 Sekunden zwischen zwei Testpaketen. T3 ist die Standardeinstellung in Nmap, die eine Parallelisierung beinhaltet. -T4 macht das Äquivalent von --max-rtt-timeout 1250 --initial-rtt-timeout 500 --max-retries 6 und setzt die maximale TCP-Scan-Verzögerung auf 10 Millisekunden. T5 macht das Äquivalent von --max-rtt-timeout 300 --min-rtt-timeout 50 --initial-rtt-timeout 250 --max-retries 2 --host-timeout 15m und setzt die maximale TCP-Scan-Verzögerung auf 5 ms.