Communitygithub.com

lan-direct

Compétence + MCP navigateur pour Claude Code et Codex : votre application et votre navigateur atteignent les services domestiques via le FAI réel pendant que l'agent reste sur le VPN. Liaison par socket, routage par hôte, sans admin, sans modification globale.

Qu'est-ce que lan-direct ?

lan-direct est une compétence d'agent IA qui résout le problème fondamental des développeurs travaillant derrière un VPN : comment une application ou un navigateur peut accéder à des services domestiques (réseau local, sites géo-restreints) sans déconnecter le VPN ni modifier les paramètres réseau globaux. Contrairement aux solutions traditionnelles qui altèrent la table de routage, les paramètres proxy système ou la configuration du client VPN, lan-direct opère exclusivement par liaison par socket au niveau du processus. Cela signifie que l'agent reste connecté au VPN tandis que l'application enfant utilise une adresse IP locale pour ses connexions sortantes. La compétence fonctionne avec Claude Code et Codex (le mécanisme est indépendant du harnais) et prend en charge Windows via PowerShell et Linux/macOS via Bash. Elle inclut plusieurs mécanismes : un préchargement Node.js qui lie chaque socket sortant sans proxy (indispensable pour les applications utilisant `fetch` natif sous Node 22-23, dont Next.js et le SDK OpenAI), un proxy HTTP pour les piles qui ne supportent pas la liaison directe, et un serveur MCP Playwright dédié qui démarre son propre proxy, permettant la navigation mixte (via ISP pour les hôtes domestiques, via VPN pour les autres) dans un même navigateur. La détection vérifie que le contournement fonctionne réellement avec deux sondes en direct avant d'autoriser la suite. La liste des hôtes à router via le FAI est fusionnée à partir de trois sources (fichier intégré, fichier utilisateur, paramètres de lancement), ce qui évite les réinstallations fréquentes. En cas d'échec de la détection (par exemple via un kill-switch du VPN), des instructions de dépannage spécifiques sont fournies. L'architecture garantit qu'aucun état global n'est modifié : les variables d'environnement sont limitées au processus enfant, le proxy s'arrête proprement, et les rares cas nécessitant une modification de la table de routage sont signalés comme une boucle d'échappement explicite.

Compatible avec✓Claude Code✓Codex CLI~Cursor
npx skills add farshadmomo/lan-direct

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait lan-direct ?

Acheminez le trafic de l'application via le FAI pendant que vous, l'agent, restez sur le VPN.

Fonctionne aussi bien avec Claude Code qu'avec Codex - le mécanisme est une liaison par socket, qui n'a rien à voir avec le harnais.

L'invariant

Ne jamais modifier la table de routage, les paramètres proxy WinINET/système ou la configuration du client VPN. Uniquement :

  • définir des variables d'environnement limitées à un processus enfant, ou
  • passer des drapeaux de liaison par outil.

Les deux sont par socket et facultatifs, ils ne peuvent donc pas toucher à votre propre connexion. C'est tout l'intérêt de la compétence - si vous utilisez route add, vous l'avez cassée (voir la section Boucle d'échappement à la fin).

Ne suggérez pas de déconnecter le VPN. C'est le problème que cette compétence existe pour éviter.

Flux de travail

1. Détecter et vérifier

powershell -NoProfile -ExecutionPolicy Bypass -File scripts\lan-detect.ps1

Sous Linux ou macOS, utilisez plutôt l'équivalent - même JSON, même contrat de code de sortie :

bash scripts/lan-detect.sh

Émet du JSON : lanIp, gateway, lanDns, subnet, tunnelActive, vpnAdapter, directEgress, lanEgress, fakeIpDns, bypassWorks. Sort avec le code 0 uniquement lorsque bypassWorks est vrai - il prouve le contournement avec deux sondes en direct plutôt que de l'inférer.

  • tunnelActive: false -> aucun VPN n'est actif. Dites-le et arrêtez-vous ; il n'y a rien à contourner.
  • bypassWorks: false avec un tunnel actif -> allez dans Dépannage ci-dessous. Ne continuez pas. Le trafic resterait silencieusement sur le VPN et vous signaleriez un faux succès.

2. Choisir le mécanisme

Backend Node (y compris Next.js) ? Ignorez le proxy - passez directement à la recette Node dans la section Recettes par pile. Une variable d'environnement, pas de processus proxy, et c'est la seule chose qui atteint le fetch natif.

Tout le reste : démarrez le proxy lié au LAN. Un processus serveur n'a pas de drapeau --interface, donc c'est ainsi qu'il obtient une sortie FAI.

node scripts/lan-proxy.mjs --bind <lanIp> --port 8899          # exécutez en arrière-plan
node scripts/lan-proxy.mjs --bind <lanIp> --port 8899 --dns <lanDns>   # si fakeIpDns: true

Il écoute uniquement sur 127.0.0.1 et enregistre chaque hôte qu'il tunnelise, afin que vous puissiez voir ce que l'application appelait réellement.

3. Redémarrer le backend en le pointant vers celui-ci

HTTP_PROXY=http://127.0.0.1:8899
HTTPS_PROXY=http://127.0.0.1:8899
NO_PROXY=localhost,127.0.0.1,<subnet>

NO_PROXY est important : sans lui, les appels du backend à ses propres services locaux sont envoyés travers le proxy pour aucune raison. (Les bases de données locales sur TCP - MySQL, Postgres, Mongo - ne sont pas HTTP et ne sont pas affectées de toute façon.)

Définissez-les sur la commande de lancement du backend, pas globalement. Voir Recettes par pile ci-dessous - HTTP_PROXY ne suffit pas pour plusieurs piles.

4. Tester et confirmer

Appelez le point d'accès dont l'appel sortant échouait. Confirmez les deux :

  • l'appel réussit maintenant, et
  • le journal du proxy affiche l'hôte qu'il a composé.

Un succès sans ligne de journal correspondante signifie que la requête n'est jamais passée par le proxy.

5. Nettoyer

Arrêtez le proxy, redémarrez le backend sans les variables d'environnement. Rien d'autre à annuler - aucun état global n'a été modifié.

pkill -f lan-proxy depuis Git Bash ne tue pas un node.exe Windows. Utilisez :

Get-CimInstance Win32_Process -Filter "Name='node.exe'" |
  Where-Object { $_.CommandLine -like '*lan-proxy*' } |
  ForEach-Object { Stop-Process -Id $_.ProcessId -Force }

Une instance résiduelle est inoffensive, mais provoquera un échec du prochain lancement en raison d'un conflit de port.

Recettes par pile

PileComment lui fournir le proxy
Python requests / httpxvariables d'environnement, telles quelles
Go, .NET HttpClientvariables d'environnement, telles quelles
PHP CLIlibcurl lit http_proxy / https_proxy depuis l'environnement du processus
Node (y compris Next.js)pas le proxy - utilisez le préchargement lan-bind.mjs, voir ci-dessous
PHP sous Apache/XAMPPvoir ci-dessous - le service n'hérite pas de votre shell
curl, wget, npm, ssh, gitignorez le proxy, liez directement (voir Liaison directe ci-dessous)

Node - utilisez le préchargement, pas le proxy

Le fetch natif s'exécute sur l'undici intégré de Node, qui ignore HTTP_PROXY sur Node <= 23 et n'accepte pas https.Agent. Vérifié sur Node 22.20 : les variables d'environnement simples, NODE_USE_ENV_PROXY=1 et --use-env-proxy ne font rien - le journal du proxy reste vide et le trafic sort silencieusement via le VPN. Cela concerne Next.js, le SDK openai et tout ce qui utilise le fetch natif.

Ignorez complètement le proxy et utilisez le préchargement, qui lie chaque socket sortant dans le processus :

LAN_BIND=<lanIp> node --import "file:///<chemin-compétence>/scripts/lan-bind.mjs" script.js
LAN_BIND=<lanIp> NODE_OPTIONS="--import file:///<chemin-compétence>/scripts/lan-bind.mjs" npm run dev

<chemin-compétence> est le répertoire de base de cette compétence avec des barres obliques - normalement C:/Users/<vous>/.claude/skills/lan-direct sous Claude Code, ou C:/Users/<vous>/.agents/skills/lan-direct sous Codex. --import nécessite une file:// absolue URL sur Windows ; un chemin Windows brut avec des antislashs échoue.

NODE_OPTIONS se propage aux workers forkés, donc il couvre les serveurs de développement Next.js et Vite.

Cela atteint le fetch natif, le SDK openai, axios, node-fetch, got et les simples http/https en même temps - pas de dépendance, pas de processus proxy, pas besoin de HTTP_PROXY. Il ignore les destinations de boucle locale, donc une base de données locale ou un serveur de développement continue de fonctionner.

Uniquement si le préchargement n'est pas disponible : Node >= 24 honore NODE_USE_ENV_PROXY=1 avec les variables d'environnement, et axios les honore sur n'importe quelle version.

PHP sous Apache / XAMPP

SetEnv/PassEnv dans httpd.conf ne remplit que $_SERVER ; libcurl lit l'environnement du processus, donc il ne les récupérera pas. Utilisez l'une des méthodes suivantes :

  • démarrez Apache depuis un shell qui a déjà http_proxy/https_proxy exportés (par exemple xampp\apache_start.bat), ou
  • putenv('https_proxy=http://127.0.0.1:8899'); avant curl_init(), ou
  • curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8899'); directement.

file_get_contents() n'honore rien de tout cela - il a besoin d'un contexte de flux avec 'proxy' => 'tcp://127.0.0.1:8899'.

Liaison directe

Aucun proxy nécessaire lorsque l'outil peut lier son propre socket :

OutilDrapeau
curl--interface <lanIp>
wget--bind-address=<lanIp>
npm--local-address=<lanIp>
ssh-b <lanIp>
Chromium / Playwrightaucun drapeau de liaison n'existe - utilisez le MCP navigateur sur le port 8900, voir ci-dessous

MCP Navigateur / Playwright

Chromium n'a pas de drapeau de liaison source, donc un navigateur n'atteint le FAI que via le proxy. Utilisez lan-browser.mjs : c'est un serveur MCP Playwright qui démarre et possède son propre proxy, donc le navigateur ne peut jamais démarrer sans.

Il est livré avec cette compétence - scripts/install.ps1 l'enregistre :

powershell -NoProfile -ExecutionPolicy Bypass -File <chemin-compétence>\scripts\install.ps1

Quels hôtes utilisent le FAI provient de trois sources fusionnées, donc c'est presque jamais une réinstallation : lan-hosts.txt dans le répertoire de la compétence (valeurs par défaut livrées, remplacées lors du git pull), ~/.lan-direct-hosts (les vôtres, jamais écrasés), et --lan-hosts a,b au lancement. Une règle par ligne, commentaires # autorisés, correspondance par suffixe.

Lorsqu'un utilisateur souhaite qu'un autre hôte soit routé via le FAI, ajoutez une ligne à ~/.lan-direct-hosts et dites-lui de redémarrer le navigateur - ne modifiez pas lan-hosts.txt, que la prochaine mise à jour écrasera.

Si l'utilisateur demande de l'enregistrer manuellement, notez que -- doit survivre au liant de paramètres de PowerShell - dispersez les arguments sous forme de tableau, ou exécutez-le depuis bash :

# depuis un clone
claude mcp add playwright-split --scope user -- \
  node <chemin-compétence>/scripts/lan-browser.mjs --lan-hosts ".ir"

# depuis npm - survit au déplacement du checkout, donc préférez-le lorsque l'utilisateur l'a installé
claude mcp add playwright-split --scope user -- npx -y lan-direct browser

Autres sous-commandes CLI, lorsque le package est installé : lan-direct detect choisit le bon script de détection pour la plateforme, et lan-direct route <host> répond "cet hôte passerait-il par le FAI ou le tunnel ?" sans démarrer de navigateur. Utilisez celle-ci lorsqu'un utilisateur signale qu'un site ne se charge pas

  • une mauvaise règle et un site en panne se ressemblent de l'extérieur.

Le serveur détecte l'IP LAN, refuse de démarrer si lan-detect indique que le contournement est cassé, réutilise un proxy existant si un autre écoute déjà, et arrête ce qu'il a démarré lorsque le MCP se ferme. Ses propres journaux vont sur stderr ; stdout est laissé propre pour JSON-RPC.

Il utilise le port 8900, délibérément pas le 8899 utilisé pour les tests backend ci-dessus. La réutilisation se fait par port uniquement, donc partager le nombre permettrait à un proxy backend qui lie tout de capturer silencieusement le navigateur et d'acheminer tout son trafic via le FAI.

La navigation mixte fonctionne dans un seul navigateur. --lan-hosts fait décider le proxy par hôte : les hôtes correspondants sortent via le FAI, tout le reste reste non lié et emprunte le tunnel. Ainsi "vérifier hoosha et youtube" ne nécessite aucun changement d'outil - hoosha sort via le FAI, youtube via le VPN, même session. Le journal du proxy montre la décision sur chaque ligne :

CONNECT  lan  hoosha.com:443
CONNECT  vpn  youtube.com:443

Gardez la liste précise : un hôte domestique manquant reçoit le tunnel et échoue avec une réponse vide, et un hôte étranger ajouté par erreur reçoit le FAI et peut être filtré. Lorsqu'un site échoue d'une manière qui ressemble à une connexion morte, vérifiez quelle route le journal a choisie avant de supposer que le site est en panne.

Pourquoi une liste explicite plutôt qu'une auto-détection : se connecter à un hôte bloqué via le tunnel réussit au niveau TCP (mesuré : connect@14ms) et ne meurt qu'environ 860 ms plus tard, après que le proxy a déjà répondu 200 Connection Established. Revenir en arrière signifierait mettre en mémoire tampon et rejouer la poignée de main TLS et payer ce délai sur chaque requête domestique.

Playwright route la boucle locale via le proxy. Chrome contourne normalement localhost, mais Playwright remplace ce comportement lorsqu'un proxy est défini, donc http://127.0.0.1:3000 arrive à lan-proxy.mjs plutôt que d'aller directement. Vérifié dans le journal du proxy. La garde de boucle locale du proxy est ce qui maintient les serveurs de développement locaux accessibles - sans elle, chacune de ces requêtes échoue avec EADDRNOTAVAIL. N'ajoutez pas --proxy-bypass=<-loopback> ; cela ne change rien ici et ne fait que brouiller l'image.

Dépannage

directEgress égal à lanEgress avec un tunnel actif. Le VPN applique un kill-switch ou un routage strict (un filtre WFP qui bloque les sockets liés). Corrigez-le dans le client VPN, pas autour : désactivez le routage strict, ou ajoutez une règle de routage direct/de contournement pour les hôtes dont vous avez besoin. nekoray/sing-box : désactivez strict_route, ou ajoutez une règle de sortie direct.

Sous Linux, cela peut également se produire sans kill-switch du tout : une adresse source seule ne remplace pas la table de routage là comme elle le fait sous Windows, donc le routage politique maintient le trafic dans le tunnel. La correction est une règle envoyant le trafic de l'IP LAN via la passerelle physique - ip rule add from <lanIp> table <n> plus une route par défaut dans cette table. Cela nécessite root et est un changement à l'échelle du système, alors expliquez-le et laissez l'utilisateur décider. Tout le reste dans cette compétence reste sans privilèges et limité au processus.

fakeIpDns: true. Le résolveur du système d'exploitation renvoie des espaces réservés 198.18.x.x qui n'ont de sens qu'à l'intérieur du tunnel. Passez --dns <lanDns> au proxy pour qu'il résolve via le DNS propre du LAN.

La sonde de sortie ne renvoie rien. Aucune connectivité vers l'hôte de la sonde. Vérifiez le lien, réexécutez.

Boucle d'échappement

Si un backend ne peut vraiment pas être proxé (un binaire compilé sans support proxy), la seule option restante est une route statique spécifique à l'hôte :

route add <targetIp> mask 255.255.255.255 <gateway> metric 1   # nécessite admin
route delete <targetIp>                                        # annuler, toujours

C'est global. Cela retire tous les processus du tunnel pour cette destination - y compris vous, si vous contactez jamais le même hôte. Nécessite une élévation, persiste jusqu'à sa suppression, et est facile à oublier. Demandez avant de l'utiliser, et supprimez-le dans la même session.

Skills associés