Erstelle einen webbasierten TCP-Portscanner

HTMLHTMLBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Im vorherigen Projekt haben wir einen Python-Portscanner entwickelt, der die Verwendung von Threading und Sockets nutzte, um TCP-Ports zu scannen. Obwohl effektiv, gibt es Möglichkeiten zur Verbesserung durch die Verwendung von Drittanbieter-Paketen.

In diesem Projekt werden wir unseren Portscanner verbessern, indem wir die Bibliothek python-nmap integrieren, um robustere Scanning-Funktionalitäten zu bieten. Darüber hinaus werden wir eine Webanwendung mit Flask erstellen, um eine benutzerfreundliche Schnittstelle für unseren Scanner bereitzustellen. Dieses schrittweise Projekt wird Sie durch den Prozess führen und gewährleisten, dass Sie folgen und auf Ihrem vorhandenen Wissen aufbauen können.

👀 Vorschau

🎯 Aufgaben

In diesem Projekt lernen Sie:

  • Wie Sie ein Flask-Projekt einrichten und seine Struktur organisieren
  • Wie Sie Flask-WTF verwenden, um Webformulare sicher zu erstellen und zu verarbeiten
  • Wie Sie Flask-Routen implementieren, um Webseitenanforderungen und -einreichungen zu verarbeiten
  • Wie Sie die Nmap-Bibliothek in Python nutzen, um Portscans durchzuführen
  • Wie Sie Scannen-Ergebnisse dynamisch auf einer Webseite mit Flask und HTML-Vorlagen anzeigen
  • Wie Sie die grundlegenden Tailwind CSS-Anwendungen verwenden, um das Design der Vorderseite zu verbessern

🏆 Errungenschaften

Nach Abschluss dieses Projekts können Sie:

  • Ein grundlegendes Verständnis der Webanwendung mit Flask demonstrieren, einschließlich Routen, Vorlagenrendern und Formularverarbeitung
  • Praktische Erfahrungen bei der Integration von Python-Skripten mit Webgrenzflächen anwenden
  • Können Sie die Fähigkeit demonstrieren, die Nmap-Bibliothek für Netzwerkscanning-Aufgaben zu verwenden
  • Flask-WTF für die Formelerstellung und -validierung in einer Webanwendung nutzen
  • Vertrautheit mit der Verwendung von Tailwind CSS für das Styling von Webseiten und die Verbesserung der Benutzeroberflächengestaltung aufweisen
  • Eine funktionierende webbasierte Anwendung erstellen, die mit Backend-Python-Skripten interagiert, um Netzwerkscans durchzuführen

Implementierung der Startseite

Um loszulegen, öffnen Sie templates/index.html und fügen Sie den folgenden Code hinzu, um sicherzustellen, dass das Formular für das Absenden von Scananforderungen richtig eingerichtet ist:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>TCP Port Scanner</title>
    <link
      href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css"
      rel="stylesheet"
    />
    <script>
      function updateButton() {
        var submitButton = document.getElementById("scanButton");
        submitButton.value = "Scanning...";
        submitButton.classList.add("cursor-not-allowed", "opacity-50");
        submitButton.disabled = true;
      }
    </script>
  </head>
  <body class="bg-gray-100 flex items-center justify-center h-screen">
    <div class="bg-white p-8 rounded-lg shadow-md">
      <h1 class="text-2xl font-bold mb-4">TCP Port Scanner</h1>
      <form action="" method="post" class="space-y-4" onsubmit="updateButton()">
        {{ form.hidden_tag() }}
        <div>
          {{ form.host.label(class="block text-sm font-medium text-gray-700") }}
          {{ form.host(class="mt-1 block w-full rounded-md border-gray-300
          shadow-sm focus:border-indigo-500 focus:ring-indigo-500") }}
        </div>
        <div>
          {{ form.ports.label(class="block text-sm font-medium text-gray-700")
          }} {{ form.ports(class="mt-1 block w-full rounded-md border-gray-300
          shadow-sm focus:border-indigo-500 focus:ring-indigo-500") }}
        </div>
        <div>
          {{ form.submit(id="scanButton", class="w-full flex justify-center py-2
          px-4 border border-transparent rounded-md shadow-sm text-sm
          font-medium text-white bg-indigo-600 hover:bg-indigo-700
          focus:outline-none focus:ring-2 focus:ring-offset-2
          focus:ring-indigo-500") }}
        </div>
      </form>
    </div>
  </body>
</html>

Die index.html-Vorlage bietet eine benutzerfreundliche Schnittstelle zum Absenden eines Hosts und eines Portbereichs zum Scannen. Das HTML-Formular umfasst zwei Hauptfelder: eines für die Hostadresse und eines für die Angabe des Portbereichs.

Flask-WTF, eine Flask-Erweiterung zur Arbeit mit WTForms, wird verwendet, um diese Felder in der Vorlage zu rendern. Die Formularabgabe wird durch eine kleine JavaScript-Funktion updateButton() verbessert, die den Text des Abschaltbuttons auf "Scanning..." ändert, wenn das Formular abgeschickt wird. Diese visuelle Rückmeldung informiert den Benutzer darüber, dass ihre Scananfrage bearbeitet wird.

Der Seitenstil wird von Tailwind CSS behandelt, einem utility-first-CSS-Framework, das die schnelle UI-Entwicklung ermöglicht.

✨ Lösung prüfen und üben

Implementierung der Scannen-Ergebnisse-Seite

Öffnen Sie templates/results.html und stellen Sie sicher, dass der folgende Code enthalten ist, um die Scannen-Ergebnisse anzuzeigen:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Scan Results</title>
    <link
      href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css"
      rel="stylesheet"
    />
  </head>
  <body class="bg-gray-100">
    <div class="flex flex-col items-center justify-center min-h-screen">
      <div class="bg-white p-8 rounded-lg shadow-lg w-full max-w-4xl">
        <h1 class="text-2xl font-bold mb-4 text-center">
          Scan Results for {{ host }}
        </h1>
        <div class="overflow-x-auto">
          <table class="table-auto w-full text-left whitespace-no-wrap">
            <thead>
              <tr
                class="text-xs font-semibold tracking-wide text-left text-gray-500 uppercase border-b dark:border-gray-700 bg-gray-50"
              >
                <th class="px-4 py-3">PORT</th>
                <th class="px-4 py-3">STATE</th>
                <th class="px-4 py-3">SERVICE</th>
                <th class="px-4 py-3">VERSION</th>
              </tr>
            </thead>
            <tbody
              class="bg-white divide-y dark:divide-gray-700 dark:bg-gray-800"
            >
              {% for result in scan_results %}
              <tr class="text-gray-700 dark:text-gray-400">
                <td class="px-4 py-3 text-sm">{{ result.port }}/tcp</td>
                <td class="px-4 py-3 text-sm">{{ result.state }}</td>
                <td class="px-4 py-3 text-sm">{{ result.name }}</td>
                <td class="px-4 py-3 text-sm">
                  {{ result.product }} {{ result.version }} {{ result.extra }}
                </td>
              </tr>
              {% endfor %}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </body>
</html>

Die results.html-Vorlage ist für das Anzeigen der Ergebnisse des Portscans verantwortlich. Sie stellt die Scannen-Ergebnisse in tabellarischer Form dar, wobei jeder Port mit seinem entsprechenden Zustand, dem Dienstnamen und der Dienstversion (sofern verfügbar) aufgelistet wird.

Diese Vorlage verwendet Tailwind CSS für das Styling, um sicherzustellen, dass die Ergebnisse-Seite sowohl responsiv als auch visuell ansprechend ist. Die Verwendung des Jinja2-Templating-Engines (integriert mit Flask) ermöglicht das dynamische Rendern von Inhalten, wobei die Scannen-Ergebnisse von der Flask-Anwendung an die Vorlage übergeben und iteriert werden, um die Tabelle zu befüllen.

✨ Lösung prüfen und üben

Initialisierung der Flask-Anwendung

In diesem Schritt werden wir das Haupt-Python-Skript für unsere Flask-Anwendung erstellen.

Fügen Sie den folgenden Code in app.py hinzu:

## Import necessary modules
from flask import Flask, render_template, request, redirect, url_for
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired, Regexp
import nmap

## Initialize Flask app
app = Flask(__name__)
app.config['SECRET_KEY'] = 'labex'

## Initialize Nmap PortScanner
nm = nmap.PortScanner()

## Define Flask-WTF form for scanning inputs
class ScanForm(FlaskForm):
    host = StringField('Host', validators=[DataRequired()])
    ports = StringField('Port Range', validators=[DataRequired(), Regexp(r'^\d+-\d+$', message="Format must be start-end")])
    submit = SubmitField('Scan')

In diesem Schritt werden die Flask-Anwendung und die Form-Klasse initialisiert.

Das app.py-Skript beginnt mit dem Importieren der erforderlichen Module, einschließlich Flask selbst, Flask-WTF für die Formularverarbeitung und Nmap für die Durchführung von Portscans. Die Flask-Anwendungsinstanz wird erstellt und mit einem Geheimschlüssel konfiguriert, um gegen CSRF-Angriffe geschützt zu werden.

Die ScanForm-Klasse definiert die Formularfelder für die Eingaben von Host und Portbereich, wobei Validatoren verwendet werden, um sicherzustellen, dass die Daten bereitgestellt werden und im richtigen Format vorliegen (insbesondere für den Portbereich).

Ersetzen Sie 'your_secret_key' durch einen echten Geheimschlüssel, der verwendet wird, um die Formulare gegen CSRF-Angriffe zu schützen.

✨ Lösung prüfen und üben

Verarbeiten der Startroute

In diesem Schritt werden wir die Startroute verarbeiten, an der Benutzer den Host und den Portbereich eingeben können, den sie scannen möchten. Fügen Sie die folgende Funktion zu app.py hinzu:

## Define route for the index page
@app.route('/', methods=['GET', 'POST'])
def index():
    form = ScanForm()  ## Instantiate the form
    if form.validate_on_submit():
        ## Get data from the form
        host = form.host.data
        ports = form.ports.data  ## Format: "start-end"
        ## Redirect to the scan route with form data
        return redirect(url_for('scan', host=host, ports=ports))
    ## Render the index page template with the form
    return render_template('index.html', form=form)

Dieser Teil des app.py-Skripts definiert die Route für die Startseite der Webanwendung. Die index()-Funktion rendert die index.html-Vorlage zusammen mit der ScanForm-Instanz.

Wenn das Formular abgeschickt und die Validierungsüberprüfungen bestanden wird, leitet die Funktion den Benutzer zur Scanroute um, wobei die Formulardaten (Host und Portbereich) über URL-Parameter mitgesendet werden. Diese Umleitung startet den Scvorgang.

✨ Lösung prüfen und üben

Implementierung der Scanroute

In diesem Schritt wird eine Route erstellt, um den tatsächlichen Scan durchzuführen und die Ergebnisse anzuzeigen. Fügen Sie die folgende Funktion zu app.py hinzu:

## Define route for the scan results
@app.route('/scan')
def scan():
    ## Retrieve host and ports from the query string
    host = request.args.get('host')
    ports = request.args.get('ports')
    ## Perform the scan using Nmap
    nm.scan(hosts=host, ports=ports, arguments='-sV')  ## -sV for service/version detection
    scan_results = []

    ## Process scan results and store them in a list
    for host in nm.all_hosts():
        for proto in nm[host].all_protocols():
            lport = nm[host][proto].keys()
            for port in lport:
                service = nm[host][proto][port]
                scan_results.append({
                    'port': port,
                    'state': service['state'],
                    'name': service.get('name', 'Unknown'),
                    'product': service.get('product', ''),
                    'version': service.get('version', ''),
                    'extra': service.get('extrainfo', '')
                })

    ## Render the results page template with the scan results
    return render_template('results.html', scan_results=scan_results, host=host)

Die scan()-Funktion behandelt die Route, die für das Durchführen des tatsächlichen Portscans und das Anzeigen der Ergebnisse verantwortlich ist. Sie erhält den Host und den Portbereich aus den in der URL übergebenen Query-String-Parametern.

Mit der Nmap PortScanner-Instanz führt es einen Scan auf dem angegebenen Host und den Ports durch, mit dem -sV-Argument, um die Dienstversionen zu erkennen.

Die Scanergebnisse werden verarbeitet und in eine Liste von Dictionaries organisiert, wobei jedes Dictionary Details zu einem gescannten Port enthält. Diese Details werden dann an die results.html-Vorlage übergeben, wo sie dem Benutzer angezeigt werden.

✨ Lösung prüfen und üben

Ausführen der Flask-Anwendung

Mit allen Komponenten an ihrem Platz sind Sie jetzt bereit, die Flask-Anwendung auszuführen und Ihren TCP-Portscanner zum Leben zu erwecken. Der letzte Codeausschnitt, den Sie in Ihrer app.py benötigen, stellt sicher, dass die Flask-Anwendung nur ausgeführt wird, wenn das Skript direkt ausgeführt wird, nicht wenn es als Modul in einem anderen Skript importiert wird. Dies ist ein üblicher Muster in Python-Anwendungen, die einen ausführbaren Skriptteil enthalten.

Fügen Sie den folgenden Codeausschnitt am Ende Ihrer app.py-Datei hinzu:

if __name__ == '__main__':
    app.run(debug=True, port=8080, host='0.0.0.0')

Dieser Code sagt Flask, Ihre Anwendung mit aktivierter Debugging-Funktion zu starten, was es einfacher macht, Fehler aufzuspüren. Die Anwendung wird auf allen Netzwerkschnittstellen lauschen (host='0.0.0.0') und Port 8080 verwenden. Der Debug-Modus sollte nur während der Entwicklung verwendet werden, da er in einer Produktionsumgebung unsicher sein kann.

Um Ihre Flask-Anwendung auszuführen, stellen Sie sicher, dass Sie sich im Projektverzeichnis befinden, in dem app.py sich befindet. Anschließend führen Sie den folgenden Befehl in der Konsole aus:

python app.py

Wechseln Sie zur Registerkarte Web 8080, um auf den TCP-Portscanner zuzugreifen. Sie können jetzt einen Host und einen Portbereich eingeben, um zu scannen, und die Ergebnisse auf der Ergebnispage anzeigen.

Die Ports 22 und 3306 sind jeweils allgemein mit den SSH- und MySQL-Diensten assoziiert, der Port 3000 wird für die WebIDE-Umgebungen verwendet.

✨ Lösung prüfen und üben

Zusammenfassung

In diesem Projekt haben Sie gelernt, wie Sie einen einfachen, aber leistungsstarken webbasierten TCP-Portscanner mit Flask und Nmap erstellen. Wir haben begonnen, indem wir die Projektumgebung eingerichtet und die erforderlichen Abhängigkeiten installiert haben. Anschließend haben wir die Flask-Anwendung erstellt, Formularabgaben behandelt, den Portscan durchgeführt und die Ergebnisse auf eine benutzerfreundliche Weise dargestellt. Dieses Projekt bietet eine hervorragende Einführung in die Webanwendung mit Flask und das Netzwerkscannen mit Nmap und liefert eine praktische Anwendung, die beide Fähigkeiten kombiniert.