detour - CLI + GUI en Go pour rediriger de façon transparente sous Windows le trafic d’une IP:PORT spécifique vers une autre destination
(github.com/LeeJeKyun)Bonjour. C’est un outil que j’ai créé parce que je me retrouvais souvent dans une situation où je voulais, pendant un moment, envoyer uniquement le trafic d’un port précis à destination d’un serveur externe vers un serveur mock lancé en local. (avec l’aide de Claude Code)
Le fichier hosts ne permet pas de faire du mapping au niveau du port, et un proxy ne fonctionne que si l’application sait reconnaître le proxy. Comme detour intercepte les paquets un niveau plus bas, dans le noyau, l’application continue simplement à fonctionner en pensant qu’elle a établi la connexion vers l’adresse d’origine.
Fonctionnement
- Interception des paquets sortants dans le noyau avec le pilote WinDivert, puis exécution d’un destination NAT en espace utilisateur → réécriture de la destination vers
TO, recalcul du checksum, puis réinjection - Pour les paquets de réponse, la source est réécrite de nouveau vers
FROMavant renvoi, de sorte que l’application croit recevoir une réponse de l’adresse qu’elle a appelée - S’applique à tout le système (pas de filtrage par PID)
Composition
detour.exe(CLI) : application d’une règle en une seule ligne avec--from 1.2.3.4:5000 --to 127.0.0.1:5001, désactivation avec Ctrl+Cdetour-gui.exe: icône dans la zone de notification + tableau multi-règles. Les règles sont enregistrées automatiquement dans%APPDATA%\detour\rules.jsonet restaurées au prochain lancement. Chaque règle exécute sa propre paire de handles WinDivert, ce qui permet d’utiliser plusieurs redirections en parallèle- Manifest UAC embarqué — double-clic pour afficher automatiquement l’invite d’élévation de privilèges
WinDivert.dll/WinDivert64.sységalement embarqués dans le binaire — pas besoin d’installer un pilote séparé, un seul.exesuffit
Stack
- Go 1.23+
- Pour la GUI,
lxn/walk(appel direct à Win32, sans dépendancecgo, donc cross-compilation possible depuis macOS) - Release sous forme d’un zip unique avec GoReleaser (CLI + GUI inclus)
Limites (v1)
- IPv4 uniquement (pas de prise en charge d’IPv6)
- Le trafic local ↔ local (
127.0.0.1) peut se comporter de manière incohérente, car la pile réseau Windows le traite de façon particulière - TCP MSS clamping non implémenté — si le MTU du chemin de redirection est plus petit, une fragmentation peut se produire
La licence est GPLv3 (WinDivert dépend de LGPLv3).
Les retours / cas d’usage / rapports de bugs sont les bienvenus.
4 commentaires
C’est donc un proxy, non ?
À proprement parler, on peut davantage voir cela comme du NAT de destination que comme un proxy. Comme l’intitulé ci-dessus est un peu trop long, je récapitule ci-dessous le cas d’usage que j’ai eu.
Je voulais envoyer les requêtes non pas vers la destination du programme client déjà compilé (1.2.3.4.:5000), mais vers le serveur de mon PC local (172.16.100.201:5000).
Comme le chemin de la requête était codé en dur, il fallait souvent demander au développeur du client de refaire un build pour le modifier.
Je voulais résoudre cela non pas au niveau de l’application, mais au niveau du noyau de l’OS, en modifiant la destination et l’en-tête de destination du trafic allant vers une IP et un port spécifiques (1.2.3.4.:5000) vers l’IP et le port souhaités (172.16.100.201:5000).
Développement de detour
Est-ce qu’il est aussi possible de proxifier les requêtes saisies sous forme d’adresse de domaine ?
Dans le cas des requêtes saisies sous forme d’adresse de domaine, nous avons estimé que la complexité de l’implémentation augmentait, donc la saisie est bloquée dès le départ... Comme cela a été développé pour des tests internes, cela ne prend pas en charge des fonctionnalités génériques.
Il est possible de trouver l’IP correspondant à un domaine donné avec
nslookup, puis de la configurer.Nous essaierons de l’intégrer dans une prochaine mise à jour.