Dieses Repo enthält Client und Server, mit denen Sie TCP- und UDP-Verkehr über andere Netzwerkprotokolle tunneln können.
Derzeit werden folgende Tunnel unterstützt:
Das Haupttool ist in Rust geschrieben und End-to-End-Tests sind in Python geschrieben.
docker pull ghcr.io/dlemel8/tunneler-server:latest
docker pull ghcr.io/dlemel8/tunneler-client:latest
cargo --version || curl --proto ' =https ' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo build --release
Es gibt auch eine Docker-Datei, wenn Sie lieber ein lokales Docker-Image erstellen möchten
docker run -e LOCAL_PORT=45301
-e REMOTE_PORT=5201
-e REMOTE_ADDRESS=localhost
-e TUNNELED_TYPE=udp
--rm -p 45301:45301 ghcr.io/dlemel8/tunneler-server:latest tcp
./target/release/client
--tunneled-type tcp
--remote-address 1.1.1.1
--remote-port 53
--log-level debug
dns
--read-timeout-in-milliseconds 100
--idle-client-timeout-in-milliseconds 30000
Führen Sie ein Docker-Image oder eine kompilierte Binärdatei mit --help
aus, um weitere Informationen zu erhalten
cargo test --all-targets
python3 -m pip install -r e2e_tests/requirements.txt
PYTHONPATH=. python3 -m pytest -v
Dieses Repo enthält einige Beispiele für die Serverbereitstellung mit Docker Compose:
Sie können jedes Beispiel lokal ausführen oder es mit Terraform und Ansible bereitstellen. Weitere Informationen finden Sie hier.
Jede ausführbare Datei enthält zwei Komponenten, die über einen Kanal von Client-Streams kommunizieren (ein Tupel von Byte-Lesern und -Schreibern):
TCP-basierter Datenverkehr wird ganz einfach in Stream umgewandelt. Die UDP-basierte Verkehrskonvertierung hängt vom Tunnelprotokoll ab.
UDP-basierter Datenverkehr benötigt außerdem eine Möglichkeit, vorhandene Clients zu identifizieren, um ihre Sitzungen fortzusetzen. Die Lösung ist ein In-Memory-Client-Cache, der eine Kennung des Clients seinem Stream zuordnet.
Um UDP-Verkehr in einen Stream umzuwandeln, wird jeder Paketnutzlast ein 2 Byte großer Header (in Big Endian) vorangestellt.
Der UDP-Listener verwendet die Peer-Adresse eingehender Pakete als Schlüssel für seinen Client-Cache.
Wir haben hier einige Herausforderungen:
Um diese Herausforderungen zu lösen, beginnt jede Client-Sitzung mit der Generierung einer zufälligen Client-ID (4 alphanumerische Zeichen). Der Client liest Daten zum Tunneln und führt sie über eine Pipeline von Encodern aus:
Verschlüsselte Daten werden dann als Name einer TXT-DNS-Abfrage verwendet.
Wenn Sie einen autorisierenden DNS-Server besitzen, kann der Client die Anfrage an einen rekursiven DNS-Resolver senden. Resolver erhält Ihre IP von Ihrem Domainnamen-Registrar und leitet die Anfrage an Ihre IP weiter. Eine weitere Option (schneller, aber für jeden Verkehrsanalysator offensichtlicher) besteht darin, den Client so zu konfigurieren, dass er die Anfrage direkt an Ihre IP sendet (an Port UDP/53 oder einen anderen Port, den der Server überwacht).
Der Server dekodiert Daten (ignoriert jeglichen Nicht-Client-Verkehr) und verwendet die Client-ID als Schlüssel für seinen Client-Cache.
Um große Serverantworten und leere TCP-ACKs zu verarbeiten, wird sowohl auf dem Client als auch auf dem Server ein Lese-Timeout verwendet. Wenn das Lese-Timeout abgelaufen ist, wird eine leere Nachricht gesendet. Sowohl der Client als auch der Server verwenden eine Leerlaufzeitüberschreitung, um die Weiterleitung zu stoppen und lokale Ressourcen zu bereinigen.
Um die gegenseitige Authentifizierung zu implementieren, verwenden wir eine private Zertifizierungsstelle:
Sowohl Client als auch Server sind so konfiguriert, dass sie ihren Schlüssel und ihr Zertifikat im TLS-Handshake verwenden. Als Root-Zertifikat wird das CA-Zertifikat verwendet.
Da die Erweiterung „Server Name Indication“ verwendet wird, fordert der Client einen bestimmten Servernamen an und der Server stellt sein Zertifikat nur bereit, wenn dieser Name angefordert wurde. Der Servername muss ebenfalls Teil des Zertifikats sein, beispielsweise als Subject Alternative Name.