In diesem Abschnitt werde ich erklären, wie man einen Tor-Proxy-Generator erstellt und eine Webanwendungsfunktion implementiert, um Proxys zu verfolgen und zu verwalten.
Die Themen dieses Abschnitts umfassen Folgendes:
- Tor-Proxy-Generator
- Automatisierte Tor-Proxy-Generierung
- Proxys erstellen
- Proxy-Status überprüfen
- Proxys löschen
- Datenbankmodelle
- Backend erstellen
- Frontend erstellen
- Test
Tor-Proxy-Generator
Das folgende GitHub-Repository enthält Code für einen Tor-Proxy-Generator:
https://github.com/0xHamy/tor_proxy_gen
Für jeden Proxy benötigen Sie einen separaten Docker-Container, zumindest mache ich das so. Sie können auch Hunderte von Proxys günstig kaufen, aber es schadet nicht, die Einrichtung selbst zu lernen.
Wenn Sie sich die Datei „docker-compose.yaml” in diesem Repository ansehen, sehen Sie, dass wir den gesamten Datenverkehr über Port 9050 innerhalb des Docker an das Host-Netzwerk über Port 9050 weiterleiten:
services:
tor:
build:
context: .
dockerfile: Dockerfile
image: tor-proxy
ports:
- "9050:9050"
container_name: tor-proxy
restart: unless-stopped
Wenn Sie über einen anderen Port als den Ihres Host-Netzwerks auf den Proxy zugreifen möchten, können Sie die Ports wie folgt ändern:
3531:9050
Der erste Port ist der Port, der auf Ihrem Host-System geöffnet wird, und der zweite Port ist der Port, der in Docker ausgeführt wird.
Die Datei torrc verwendet Port 9050 für den Tor-Dienst:
SocksPort 0.0.0.0:9050
Log notice stdout
Dockerfile führt eine kleine Version des Debian-Betriebssystems aus, um den Tor-Proxy auszuführen:
# Use a lightweight Debian-based image
FROM debian:bullseye-slim
# Install Tor
RUN apt-get update && \
apt-get install -y tor && \
rm -rf /var/lib/apt/lists/*
# Copy custom Tor configuration
COPY torrc /etc/tor/torrc
# Expose the Tor SOCKS5 proxy port
EXPOSE 9050
# Run Tor as the main process
CMD ["tor", "-f", "/etc/tor/torrc"]
Wenn es darum geht, eine App zu erstellen, die mehrere Tor-Proxys generiert, können wir uns nicht nur auf Port 9050 verlassen, da dieser bereits belegt ist und wir ihn daher nicht verwenden können, wenn er bereits von etwas anderem genutzt wird. Aus diesem Grund erstellen wir ein Python-Skript, das einen zufälligen Port zwischen 40.000 und 60.000 auswählt. Da es in jedem Computer nur 65.535 Ports gibt, haben wir diesen bestimmten Portbereich gewählt, da er meiner Erfahrung nach normalerweise nicht verwendet wird und zumindest unter Ubuntu keine Root-Rechte erfordert.
Automatisierte Tor-Proxy-Generierung
Da wir Tor-Proxys mit Docker generieren, müssen wir drei Kernfunktionen implementieren:
- Eine Funktion zum Erstellen eines Docker-Containers für die Ausführung eines Tor-Proxys
- Eine Funktion zum Überprüfen des Status eines Docker-Containers, um zu überprüfen, ob der Proxy aktiv ist
- Eine Funktion zum Herunterfahren und Entfernen eines Docker-Containers
Die entsprechenden Dateien befinden sich in app/services/*.py. Die spezifischen Dateien, die wir verwenden werden, sind:
tor_proxy_gen.py: Erstellt Docker-Container für Tor-Proxyscontainer_status.py: Überprüft den Status von Docker-Containernrm_container.py: Verwaltet das Löschen von Docker-Containern
Proxys erstellen
Das Skript tor_proxy_gen.py automatisiert die Erstellung von Docker-Containern, auf denen Tor-Proxys ausgeführt werden, und stellt einen SOCKS5-Proxy für den anonymen Netzwerkzugriff bereit. Nachfolgend finden Sie eine kurze Erläuterung der Komponenten und Funktionen.
Zweck:
- Erstellt und startet einen Docker-Container, auf dem ein Tor-Proxy ausgeführt wird, weist einen zufälligen Port zu, ruft die IP-Adresse des Containers und die IP-Adresse des Tor-Ausgangsknotens ab und gibt die Details als JSON-fähiges Wörterbuch zurück.
Global Variables:
PORT_MIN,PORT_MAX:- Zweck: Definiert den Bereich (40001–60001) für die Auswahl zufälliger Host-Ports.
- Details: Stellt die eindeutige Portzuweisung für jeden Container sicher.
SOCKS_PORT_IN_CONTAINER:- Zweck: Legt den Tor-SOCKS-Port innerhalb des Containers fest (9050).
- Details: Standardport für den SOCKS5-Proxy von Tor.
MAX_PORT_ATTEMPTS:- Zweck: Begrenzt die Anzahl der Versuche, einen freien Port zu finden (100).
- Details: Verhindert Endlosschleifen bei der Port-Auswahl.
WAIT_MAX_SECONDS,WAIT_STEP_SECONDS:- Zweck: Steuert das Zeitlimit (60 s) und das Abfrageintervall (2 s) für die Portbereitschaft.
- Details: Wird verwendet, wenn auf die Öffnung des Containerports gewartet wird.
DOCKERFILE,TORRC,COMPOSE_TEMPLATE:- Zweck: Definiert Docker-Konfigurationsdateien als Zeichenfolgen.
- Details:
DOCKERFILErichtet ein Debian-basiertes Image mit Tor ein;TORRCkonfiguriert den SOCKS-Port von Tor;COMPOSE_TEMPLATEdefiniert die Docker Compose-Einstellungen für den Container.
Funktionen:
-
die:- Zweck: Protokolliert eine Fehlermeldung und beendet das Programm.
- Wichtige Parameter:
msg(Fehlermeldung),code(Exit-Code, Standardwert 1). - Rückgabewerte: Keine (beendet das Programm).
- Details: Gibt den Fehler an stderr aus und protokolliert ihn über
logging.
-
cmd_exists:- Zweck: Prüft, ob eine ausführbare Datei (z. B.
docker) in$PATHverfügbar ist. - Wichtige Parameter:
executable(Befehlsname). - Rückgabewerte: Boolesch (
True, wenn gefunden). - Details: Verwendet
shutil.whichund protokolliert das Ergebnis.
- Zweck: Prüft, ob eine ausführbare Datei (z. B.
-
docker_compose_available:- Zweck: Überprüft, ob Docker Compose verfügbar ist.
- Wichtige Parameter: Keine.
- Rückgabewert: Boolescher Wert (
True, wenndocker compose versionerfolgreich ist). - Details: Führt einen Befehl aus, um nach Docker Compose zu suchen, und protokolliert die Ausgabe oder Fehler.
-
is_port_free:- Zweck: Überprüft, ob ein TCP-Port auf
127.0.0.1unbenutzt ist. - Wichtige Parameter:
port(Portnummer). - Rückgabewert: Boolescher Wert (
True, wenn der Port frei ist). - Details: Versucht, mit einem Socket und einer Zeitüberschreitung von 0,5 Sekunden eine Verbindung zum Port herzustellen.
- Zweck: Überprüft, ob ein TCP-Port auf
-
random_free_port:- Zweck: Sucht einen zufälligen, ungenutzten Port im definierten Bereich.
- Wichtige Parameter: Keine.
- Rückgabewert: Ganzzahl (freie Portnummer).
- Details: Versucht bis zu
MAX_PORT_ATTEMPTSzufällige Ports; ruftdieauf, wenn keiner frei ist.
-
random_container_name:- Zweck: Generiert einen eindeutigen Containernamen.
- Wichtige Parameter: Keine.
- Rückgabewert: Zeichenfolge (z. B.
torproxy_abcdef). - Details: Kombiniert
torproxy_mit sechs zufälligen Kleinbuchstaben.
-
wait_for_port:- Zweck: Wartet, bis ein Port auf einem Host geöffnet ist oder die Zeit abgelaufen ist.
- Wichtige Parameter:
host(IP),port(Portnummer),timeout(Sekunden). - Rückgabewert: Keine (löst bei Zeitüberschreitung einen
RuntimeErroraus). - Details: Fragt alle
WAIT_STEP_SECONDSab, bis der Port verwendet wird odertimeoutabläuft.
-
fetch_tor_exit_ip:- Zweck: Ruft die IP-Adresse des Tor-Ausgangsknotens über externe Dienste ab.
- Wichtige Parameter:
host_port(Proxy-Port),timeout(Zeitüberschreitung für die Anfrage, standardmäßig 15 Sekunden). - Rückgabewert: Zeichenfolge (IP-Adresse des Ausgangsknotens).
- Details: Fragt IP-Echo-Dienste (z. B.
checkip.amazonaws.com) über einen SOCKS5-Proxy ab; löstRuntimeErroraus, wenn alle fehlschlagen.
-
create_and_start_proxy:- Zweck: Erstellt einen Tor-Proxy-Container, startet ihn und gibt seine Details zurück.
- Wichtige Parameter: Keine.
- Rückgabewerte: Wörterbuch mit
container_name,container_ip(mit Port),tor_exit_nodeundtimestamp. - Details:
- Überprüft die Verfügbarkeit von Docker und Compose; bricht ab, wenn diese fehlen.
- Generiert einen zufälligen Containernamen und Port.
- Erstellt ein temporäres Verzeichnis mit
Dockerfile,torrcundcompose.yaml. - Führt
docker compose up --build -daus, um den Container zu starten. - Wartet, bis der Port geöffnet ist, ruft die IP-Adresse des Containers über
docker inspectab und ruft die Tor-Ausgangs-IP ab. - Bereinigt den Container bei einem Fehler mit „docker rm -f“.
Auf meinem Rechner benötigt Docker „sudo“ für Root-Rechte. Wenn Sie „tor_proxy_gen.py“ mit „sudo python3 tor_proxy_gen.py“ ausführen, wird der systemweite Python-Interpreter verwendet, der die virtuelle Umgebung mit den Abhängigkeiten des Projekts „tornet_scraper“ umgeht.
Führen Sie stattdessen das Skript wie folgt aus, um den Python-Interpreter der virtuellen Umgebung zu verwenden:
-> % sudo /home/hamy/tornet_scraper/venv/bin/python3 app/services/tor_proxy_gen.py
[sudo] password for hamy:
{
"container_name": "torproxy_tucgye",
"proxy_ip_docker": "192.168.128.2:45364",
"proxy_ip_exit_node": "185.193.52.180",
"timestamp": 1752431067
}
Dadurch wird sichergestellt, dass das Skript den Python-Interpreter der virtuellen Umgebung „tornet_scraper” mit allen erforderlichen Abhängigkeiten verwendet.
Überprüfen des Proxy-Status
Das Skript „container_status.py” enthält Hilfsfunktionen zum Überprüfen des Status von Docker-Containern. Nachfolgend finden Sie eine kurze Erläuterung der Funktionen.
-
cmd_exists:- Zweck: Überprüft, ob eine bestimmte ausführbare Datei im
$PATHdes Systems verfügbar ist. - Wichtige Parameter:
executable: String-Name des Befehls (z. B.docker).
- Rückgabewert: Boolescher Wert (
True, wenn die ausführbare Datei gefunden wurde, andernfallsFalse). - Details: Verwendet
shutil.which, um zu überprüfen, ob die ausführbare Datei vorhanden und im$PATHdes Systems zugänglich ist.
- Zweck: Überprüft, ob eine bestimmte ausführbare Datei im
-
container_running:- Zweck: Stellt fest, ob ein Docker-Container ausgeführt wird.
- Wichtige Parameter:
name: String-Name des Docker-Containers.
- Rückgabewert: Boolescher Wert (
True, wenn der Container vorhanden ist und ausgeführt wird, andernfallsFalse). - Details: Führt „sudo docker inspect -f {{.State.Running}}
“ aus, um den Ausführungsstatus des Containers zu überprüfen. Gibt „True“ zurück, wenn die Ausgabe „true“ lautet, „False“, wenn der Befehl fehlschlägt (z. B. wenn der Container nicht existiert) oder der Status nicht „running“ ist. Unterdrückt stderr mit „DEVNULL“, um Fehlerausgaben zu vermeiden.
Proxys löschen
Das Skript „rm_container.py“ bietet eine Funktion zum zwangsweisen Entfernen eines Docker-Containers. Nachfolgend finden Sie eine kurze Erläuterung der einzigen Funktion.
-
„delete_container“:
- Zweck: Löscht einen angegebenen Docker-Container mit „sudo docker rm -f“.
- Wichtige Parameter:
name: String-Name des zu löschenden Docker-Containers.
- Rückgabewerte: Boolesche Werte (
True, wenn das Löschen erfolgreich war,False, wenn es fehlgeschlagen ist). - Details: Führt
sudo docker rm -f <name>aus, um den Container zwangsweise zu entfernen, wobei sowohl stdout als auch stderr mitDEVNULLunterdrückt werden. GibtTruezurück, wenn der Befehl erfolgreich war, oderFalse, wenn einCalledProcessErrorauftritt (z. B. wenn der Container nicht existiert oder Berechtigungsprobleme vorliegen).
Datenbankmodelle
So sehen Ihre Datenbankmodelle aus:
class Proxy(Base):
__tablename__ = "proxies"
id = Column(Integer, primary_key=True, index=True)
container_name = Column(String, unique=True, index=True)
container_ip = Column(String)
tor_exit_node = Column(String)
timestamp = Column(DateTime, default=datetime.utcnow)
running = Column(Boolean, default=True)
Einigen von Ihnen erscheint datetime.utcnow möglicherweise als veraltet, aber darüber müssen Sie sich keine Gedanken machen.
Backend erstellen
Die Services-Module übernehmen die ganze Arbeit, aber wir benötigen noch einen Backend-Router, um diese Funktionen aufzurufen und Anfragen vom Frontend zu bearbeiten. Ihr Backend für die Proxy-Generierung befindet sich in app/routes/proxy_gen.py.
Das Skript proxy_gen.py definiert FastAPI-Routen zum Erstellen, Löschen und Auflisten von Tor-Proxy-Containern sowie zur Interaktion mit der Datenbank und externen Diensten. Nachfolgend finden Sie eine kurze Erläuterung der Komponenten und Funktionen.
Globale Variablen
logger:- Zweck: Konfiguriert die Protokollierung für die Fehlerbehebung und Fehlerverfolgung.
- Details: Verwendet das Modul
loggingmit der StufeINFO, um Vorgänge und Fehler zu protokollieren.
proxy_gen_router:- Zweck: FastAPI-Router für proxybezogene Endpunkte.
- Details: Konfiguriert mit dem Präfix
/api/proxy-genund den Tags[„API“, „Proxy Generator“]zur Organisation.
Funktionen
-
create_proxy:- Zweck: Erstellt einen neuen Tor-Proxy-Container und speichert dessen Details in der Datenbank.
- Wichtige Parameter:
request: FastAPI-Request-Objekt für die Sitzungsverwaltung.db: SQLAlchemy-Sessionfür Datenbankoperationen (überDepends(get_db)).
- Rückgabewerte:
JSONResponsemit Erfolgsstatus, Meldung und Proxy-Details (Containername, IP, Tor-Ausgangsknoten, Zeitstempel, Ausführungsstatus). - Details: Ruft
create_and_start_proxy(austor_proxy_gen.py) auf, um einen Container zu starten, erstellt eineProxy-Modellinstanz, speichert sie in der Datenbank und gibt eine JSON-Antwort zurück. Löst bei FehlernHTTPException(500) aus und protokolliert das Problem.
-
delete_proxy:- Zweck: Löscht einen angegebenen Tor-Proxy-Container und seinen Datenbankeintrag.
- Wichtige Parameter:
container_name: String-Name des zu löschenden Containers.request: FastAPI-ObjektRequestfür sitzungsbasierte Flash-Meldungen.db: SQLAlchemy-ObjektSessionfür Datenbankoperationen.
- Rückgabewert:
JSONResponsemit Status und Meldung bei erfolgreicher Löschung. - Details: Fragt die Tabelle
Proxynach dem Container ab; wenn er gefunden wird, ruft erdelete_container(ausrm_container.py) auf, um ihn zu entfernen. Löscht bei Erfolg den Datenbankeintrag und fügt eine erfolgreiche Flash-Meldung zur Sitzung hinzu. LöstHTTPExceptionaus (404, wenn nicht gefunden, 500 bei Fehlern) und fügt Fehler-Flash-Meldungen hinzu.
-
list_proxies:- Zweck: Ruft eine Liste aller Proxys mit aktualisiertem Ausführungsstatus ab.
- Wichtige Parameter:
db: SQLAlchemySessionfür Datenbankoperationen.
- Rückgabewerte:
JSONResponsemit einer Liste von Proxys, die jeweils den Containernamen, die IP-Adresse, den Tor-Ausgangsknoten, den Zeitstempel und den Ausführungsstatus enthalten. - Details: Fragt alle
Proxy-Datensätze ab, überprüft den Ausführungsstatus jedes Containers mitcontainer_running(auscontainer_status.py), aktualisiert bei Bedarf das Feldrunningin der Datenbank und gibt die Liste als JSON zurück. Bei Fehlern wird eineHTTPException(500) ausgelöst und das Problem protokolliert.
Frontend erstellen
Ihr Vorlagencode befindet sich in app/templates/proxy_gen.html.
Die Vorlage proxy_gen.html erweitert base.html um eine Benutzeroberfläche zur Verwaltung von Tor-Proxy-Containern in der Anwendung tornet_scraper, die über API-Aufrufe mit dem Backend interagiert. Im Folgenden finden Sie eine kurze Erläuterung der wichtigsten Funktionen und ihrer Interaktion mit dem Backend.
-
Vorlagenvererbung:
- Zweck: Nutzt das Layout von
base.htmlfür eine einheitliche Struktur. - Backend-Interaktion: Erbt die Navigationleiste und die Verarbeitung von Flash-Meldungen aus
base.html. Der{% block title %}setzt den Seitentitel auf „Proxy Generator“ und{% block content %}definiert die seitenbezogenen Funktionen. Flash-Meldungen aus dem Backend (die in der Sitzung gespeichert sind) werden im geerbten Container angezeigt.
- Zweck: Nutzt das Layout von
-
Proxy-Erstellung:
- Zweck: Initiiert und bestätigt die Erstellung eines neuen Tor-Proxy-Containers.
- Backend-Interaktion:
- Eine Schaltfläche „Neuen Proxy erstellen“ löst die JavaScript-Funktion
createProxy()aus und öffnet ein Bestätigungsmodal. - Die Schaltfläche „Weiter“ des Modals ruft
confirmCreateProxy()auf und sendet eine AJAX-POST-Anfrage an/api/proxy-gen/create(verarbeitet vonproxy_gen.py::create_proxy). - Das Backend erstellt einen Docker-Container (über
tor_proxy_gen.py), speichert die Proxy-Details (Containername, IP, Tor-Ausgangsknoten, Zeitstempel, Ausführungsstatus) in der TabelleProxyin der Datenbank und gibt eine JSON-Antwort zurück. - Bei Erfolg wird die Tabelle über
updateProxyTable()aktualisiert. Fehler lösen Konsolenprotokolle aus und aktivieren die Schaltfläche erneut.
- Eine Schaltfläche „Neuen Proxy erstellen“ löst die JavaScript-Funktion
-
Anzeige und Aktualisierung der Proxy-Tabelle:
- Zweck: Zeigt eine dynamische Liste von Proxys mit Statusaktualisierungen in Echtzeit an.
- Backend-Interaktion:
- Beim Laden der Seite rendert Jinja2 die anfänglichen Proxy-Daten (
proxiesausmain.py::proxy_gen) in eine Tabelle mit Spalten für Containername, IP, Tor-Ausgangsknoten, Zeitstempel und Status. - Die Funktion
updateProxyTable()wird alle 10 Sekunden (übersetInterval) und bei Erstellung/Löschung ausgeführt und sendet eine AJAX-GET-Anfrage an/api/proxy-gen/list(verarbeitet vonproxy_gen.py::list_proxies). - Das Backend fragt die Tabelle „Proxy“ ab, überprüft den Ausführungsstatus jedes Containers (über „container_status.py::container_running“), aktualisiert bei Bedarf die Datenbank und gibt eine JSON-Liste der Proxys zurück.
- Die Tabelle wird gelöscht und mit den neuesten Daten neu gefüllt, wobei der Status mit farbigen Badges als „Running“ (Ausgeführt) oder „Not Running“ (Nicht ausgeführt) angezeigt wird.
- Beim Laden der Seite rendert Jinja2 die anfänglichen Proxy-Daten (
-
Proxy löschen:
- Zweck: Ermöglicht Benutzern das Löschen eines Proxy-Containers.
- Backend-Interaktion:
- Jede Tabellenzeile verfügt über eine Schaltfläche „Löschen“, die
openDeleteModal(containerName)aufruft, um ein Bestätigungsmodal mit dem in einem versteckten Eingabefeld gespeicherten Containernamen zu öffnen. - Die Schaltfläche „Löschen“ des Modals löst
confirmDeleteProxy()aus, wodurch eine AJAX-DELETE-Anfrage an/api/proxy-gen/delete/{container_name}gesendet wird (verarbeitet durchproxy_gen.py::delete_proxy). - Das Backend überprüft, ob der Proxy in der Tabelle „Proxy“ vorhanden ist, löscht den Container (über „rm_container.py::delete_container“), entfernt den Datenbankeintrag und fügt eine Erfolgsmeldung zur Sitzung hinzu.
- Bei Erfolg wird eine Erfolgsmeldung angezeigt (über „showFlashMessage“) und die Tabelle wird aktualisiert. Fehler lösen eine Fehlermeldung aus.
- Jede Tabellenzeile verfügt über eine Schaltfläche „Löschen“, die
Testen
Führen Sie die Web-App aus:
sudo /home/hamy/tornet_scraper/venv/bin/python3 -m uvicorn app.main:app --reload
Öffnen Sie die Web-App:
http://127.0.0.1:8000/proxy-gen
Erstellen Sie einen Proxy:
