Ce référentiel contient un client et un serveur qui vous permettent de tunneliser le trafic TCP et UDP sur d'autres protocoles réseau.
Actuellement, les tunnels pris en charge sont :
L'outil principal est écrit en Rust et les tests de bout en bout sont écrits en Python.
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
Il existe également un fichier Docker si vous préférez créer une image Docker locale
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
Exécutez l'image Docker ou le binaire compilé avec --help
pour plus d'informations
cargo test --all-targets
python3 -m pip install -r e2e_tests/requirements.txt
PYTHONPATH=. python3 -m pytest -v
Ce dépôt contient quelques exemples de déploiement de serveur utilisant Docker Compose :
Vous pouvez exécuter chaque exemple localement ou le déployer à l'aide de Terraform et Ansible. Voir plus d’informations ici.
Chaque exécutable contient 2 composants communiquant via un canal de flux clients (un tuple d'octets lecteur et écrivain) :
Le trafic basé sur TCP est trivialement converti en flux. La conversion du trafic basée sur UDP dépend du protocole de tunnel.
Le trafic basé sur UDP a également besoin d'un moyen d'identifier les clients existants pour poursuivre leurs sessions. La solution est un cache clients en mémoire qui mappe un identifiant du client à son flux.
Afin de convertir le trafic UDP en flux, un en-tête de 2 octets (en big endian) précède chaque charge utile de paquet.
L'écouteur UDP utilise l'adresse homologue du paquet entrant comme clé de son cache client.
Nous avons ici quelques défis :
Pour résoudre ces défis, chaque session client commence par générer un ID client aléatoire (4 caractères alphanumériques). Le client lit les données dans un tunnel et les exécute via un pipeline d'encodeurs :
Les données codées sont ensuite utilisées comme nom d'une requête DNS TXT.
Si vous possédez un serveur DNS faisant autorité, le client peut envoyer la requête à un résolveur DNS récursif. Le résolveur obtiendra votre IP auprès de votre registraire de nom de domaine et transmettra la demande à votre IP. Une autre option (plus rapide mais plus évidente pour tout analyseur de trafic) consiste à configurer le client pour qu'il envoie la requête directement à votre IP (sur le port UDP/53 ou sur tout autre port que le serveur écoute).
Le serveur décode les données (en ignorant tout trafic non client) et utilise l'ID client comme clé de son cache clients.
Afin de gérer les réponses volumineuses du serveur et les ACK TCP vides, le délai d'attente de lecture est utilisé à la fois sur le client et sur le serveur. Si le délai de lecture est expiré, un message vide sera envoyé. Le client et le serveur utilisent le délai d'inactivité pour arrêter le transfert et nettoyer les ressources locales.
Pour mettre en œuvre l'authentification mutuelle, nous utilisons une autorité de certification privée :
Le client et le serveur sont configurés pour utiliser leur clé et leur certificat dans la négociation TLS. Le certificat CA est utilisé comme certificat racine.
Étant donné que l'extension Server Name Indication est utilisée, le client demande un nom de serveur spécifique et le serveur ne délivre son certificat que si ce nom a été demandé. Le nom du serveur doit également faire partie du certificat, par exemple en tant que nom alternatif du sujet.