Einführung
In diesem Projekt entwickeln wir einen Server-Port-Scanner mit Python, um offene Ports auf einem Zielserver aufzuspüren. Dieses Tool ist von entscheidender Bedeutung für Systemadministratoren, die damit Sicherheitsrichtlinien verifizieren, sowie für potenzielle Angreifer, die damit aktive Netzwerkdienste auf einem Host identifizieren. Unser Weg führt uns durch die essenziellen Aspekte des Port-Scannings, inklusive der Methodik und deren Bedeutung. Wir vertiefen uns in die Erstellung eines einfachen, aber effektiven Port-Scanners unter Nutzung der Python-Funktionen, wobei wir uns auf einen Multi-Threading-Ansatz konzentrieren, um die Effizienz und Performance zu steigern.
Port-Scanning ist der Prozess des Sendens von Anfragen an eine Reihe von Server-Ports, um festzustellen, welche davon offen sind. Dieser Schritt ist sowohl für die Aufrechterhaltung der Sicherheit als auch für das Auffinden verwundbarer Dienste kritisch. Wir beginnen mit der Untersuchung der Grundlagen des Port-Scannings und seiner Auswirkungen.
Kernkonzepte:
- Port-Scanner helfen dabei, offene Ports auf einem Server oder Host zu erkennen.
- Sie werden für Sicherheitsbewertungen sowie von Angreifern zur Identifizierung verwundbarer Dienste eingesetzt.
- Die einfachste Form des Port-Scannings besteht darin, TCP-Verbindungsversuche zu einer Reihe von Ports durchzuführen.
👀 Vorschau
Hier ist ein kleiner Einblick in das Port-Scanner-Tool, das wir bauen werden:
python port_scanner.py 127.0.0.1 5000-9000
Ausgabe:
Opened Port: 8081
Scanning completed.
🎯 Aufgaben
In diesem Projekt lernen Sie:
- Wie Sie Pythons Socket-Programmierung nutzen, um mit Netzwerk-Ports zu interagieren.
- Wie Sie einen Multi-Threading-Ansatz in Python implementieren, um die Effizienz von Netzwerk-Scanning-Aufgaben zu erhöhen.
- Wie Sie ein Kommandozeilen-Tool in Python entwickeln, das Benutzereingaben für flexibles Port-Scanning entgegennimmt.
🏆 Lernerfolge
Nach Abschluss dieses Projekts sind Sie in der Lage:
- Die Python-Bibliothek
socketzu verwenden, um Netzwerkverbindungen herzustellen, die Port-Verfügbarkeit zu prüfen und Netzwerk-Ausnahmen zu behandeln. - Multi-Threading in Python zu verstehen und anzuwenden, um gleichzeitige Aufgaben auszuführen, was die Leistung netzwerkintensiver Operationen erheblich verbessert.
- Ein praktisches Kommandozeilen-Tool für Port-Scans zu bauen und dabei Ihre Fähigkeiten im Python-Scripting sowie im Parsen von Kommandozeilenargumenten zu vertiefen.
TCP-Verbindungstests etablieren
Unser erster Schritt besteht darin, eine Funktion zu schreiben, die prüft, ob ein TCP-Port auf der Ziel-IP offen ist. Diese Funktion versucht, eine Verbindung zu einem bestimmten Port herzustellen und dessen Status zu ermitteln.
Öffnen Sie die Datei port_scanner.py im Verzeichnis /home/labex/project und fügen Sie die folgende Python-Funktion hinzu:
import argparse
from queue import Queue
from socket import AF_INET, gethostbyname, socket, SOCK_STREAM
import threading
def tcp_test(port: int, target_ip: str) -> None:
with socket(AF_INET, SOCK_STREAM) as sock:
sock.settimeout(1)
result = sock.connect_ex((target_ip, port))
if result == 0:
print(f"Opened Port: {port}")
Dieser Code definiert die Funktion tcp_test, die versucht, eine TCP-Verbindung zu einem angegebenen Port auf der Ziel-IP-Adresse aufzubauen. Es wird ein Timeout gesetzt, um lange Wartezeiten bei jedem Port zu vermeiden, und connect_ex verwendet, um den Verbindungsversuch zu starten.
Wenn connect_ex den Wert 0 zurückgibt, bedeutet dies, dass die Verbindung erfolgreich war – der Port ist also offen. Die Funktion gibt daraufhin eine Meldung über den offenen Port aus.
Nebenläufige Port-Prüfungen einrichten
Als Nächstes erstellen wir eine worker-Funktion. Diese wird von jedem Thread verwendet, um Ports aus einer Warteschlange (Queue) zu verarbeiten und die tcp_test-Funktion aufzurufen, um den Status jedes Ports zu prüfen.
Fügen Sie den folgenden Code zu Ihrer port_scanner.py hinzu:
def worker(target_ip: str, queue: Queue) -> None:
while not queue.empty():
port = queue.get()
tcp_test(port, target_ip)
queue.task_done()
Die worker-Funktion ist darauf ausgelegt, von mehreren Threads gleichzeitig ausgeführt zu werden. Sie ruft kontinuierlich Portnummern aus einer Queue ab und nutzt die zuvor definierte tcp_test-Funktion, um zu prüfen, ob diese Ports auf der Ziel-IP offen sind.
Nachdem ein Port getestet wurde, markiert sie die Aufgabe in der Queue als erledigt. Diese Funktion ermöglicht das gleichzeitige Scannen von Ports, was den gesamten Prozess erheblich beschleunigt.
Orchestrierung des Scan-Prozesses
Die main-Funktion steuert den Scan-Prozess, indem sie die Queue einrichtet, die Worker-Threads initialisiert und den Scan-Vorgang über den angegebenen Portbereich verwaltet.
Fügen Sie nun die main-Funktion zu Ihrer port_scanner.py hinzu:
def main(host: str, start_port: int, end_port: int) -> None:
target_ip = gethostbyname(host)
queue = Queue()
for port in range(start_port, end_port + 1):
queue.put(port)
for _ in range(100): ## Adjust the number of threads if necessary
t = threading.Thread(target=worker, args=(target_ip, queue,))
t.daemon = True
t.start()
queue.join()
print("Scanning completed.")
Die main-Funktion orchestriert den gesamten Port-Scanning-Ablauf.
Zuerst löst sie den Ziel-Hostnamen in eine IP-Adresse auf und erstellt dann eine Queue für die zu scannenden Portnummern. Sie befüllt die Queue mit allen Ports im angegebenen Bereich und startet mehrere Worker-Threads (in diesem Beispiel 100), die die Queue parallel abarbeiten. Die Funktion wartet, bis alle Ports verarbeitet wurden (queue.join()), und gibt dann eine Meldung aus, dass der Scan abgeschlossen ist.
Den Port-Scanner ausführen
Schließlich ist es an der Zeit, unseren Port-Scanner zu testen. Wir werden einen Bereich von Ports auf dem Localhost scannen, um unser Werkzeug zu überprüfen.
Fügen Sie die folgenden Zeilen am Ende Ihrer port_scanner.py hinzu, um das Skript ausführbar zu machen:
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='TCP Port Scanner')
parser.add_argument('host', help='Host to scan')
parser.add_argument('ports', help='Port range to scan, formatted as start-end')
args = parser.parse_args()
start_port, end_port = map(int, args.ports.split('-'))
main(args.host, start_port, end_port)
Dieser Code implementiert das Parsen von Kommandozeilenargumenten, was das Skript vielseitiger und benutzerfreundlicher macht.
Durch die Verwendung der argparse-Bibliothek werden zwei erforderliche Argumente definiert: host und ports.
- Das Argument
hostdient zur Angabe der Zieladresse oder des Hostnamens, den Sie scannen möchten. - Das Argument
portserwartet eine Zeichenfolge, die den zu scannenden Portbereich im Format "Start-Ende" definiert (z. B. "5000-8000"). Das Skript teilt diese Zeichenfolge am Trennzeichen-instart_portundend_portauf und wandelt sie in Ganzzahlen um. Dies ermöglicht es Benutzern, das Ziel und den Portbereich einfach beim Aufruf des Skripts im Terminal anzugeben.
Führen Sie den Scanner nun mit dem folgenden Befehl im Terminal aus:
python port_scanner.py 127.0.0.1 5000-9000
Ausgabe:
Opened Port: 8081
Scanning completed.
Nachdem Sie mit dem Port-Scanner einen offenen Port (8081) identifiziert haben, auf dem ein Webserver läuft, können Sie untersuchen, was dort gehostet wird.
Klicken Sie dazu zuerst auf die Schaltfläche "Hinzufügen" (Plus-Icon) und wählen Sie die Option "Web Service".

Geben Sie dann den Port 8081 ein und klicken Sie auf die Schaltfläche "Access".

Sie werden den Webserver finden, der in Ihrem System läuft und auf Port 8081 lauscht.

Zusammenfassung
In diesem Projekt haben wir einen grundlegenden Port-Scanner mit Python konstruiert, angefangen bei der fundamentalen tcp_test-Funktion bis hin zu einem Multi-Threaded-Scanning-Ansatz. Wir haben den Prozess in überschaubare Schritte zerlegt, was in einem funktionalen Werkzeug gipfelte, das offene Ports auf einem Zielserver identifizieren kann. Durch diese praktische Erfahrung haben wir nicht nur unser Verständnis für Netzwerksicherheit vertieft, sondern auch unsere Fähigkeiten in der Python-Programmierung und im Management von Nebenläufigkeit geschärft.



