mitmproxy, DevTools, Gradle: drie lagen achter de VPN
Loopback komt nooit in de tunnel. Rangschik het symptoom als listener, truststore of packetfilter, en repareer de laag die werkelijk faalde.
De VPN verbindt, en drie losstaande tools falen op drie verschillende manieren dezelfde middag. mitmproxy ziet geen verzoeken meer, Chrome weigert de debugger, en Gradle gooit BindException bij het binden van een lokale socket. Het gedeelde vermoeden is dat de tunnel localhost blokkeert. Dat kan niet: 127.0.0.1 wordt in de kernel afgehandeld en bereikt nooit een adapter, laat staan een gateway.
Drie lagen, drie verschillende breuken
Wat er met de client veranderde, is niet de route naar loopback. Het zijn een lokale proxy, een truststore op de machine en een packetfilter, en elk breekt een ander deel van de workflow van een ontwikkelaar. Een symptoom in de juiste rij plaatsen is het grootste deel van de diagnose:
| Symptom | Layer | First check |
|---|---|---|
| Proxy sees no traffic | Local proxy or listener | ss -lntp, or netstat -ano on Windows |
| TLS error in one tool only | Trust store | Which CA bundle does that runtime read? |
| Local bind or connect refused | Packet filter or port owner | Who holds the port, and what rule drops it? |
Bijna elk rapport van dit soort begint bij de laatste rij en werkt omhoog, wat achterstevoren is. De tunnel is de enige laag die aantoonbaar geen loopback-verkeer kan zien, dus verdient die het minste wantrouwen. Begin met wat het proces bond, vraag dan welke certificaten het vertrouwt, en kijk pas daarna naar het beleid op de machine.
Begin bij de listener, niet bij de tunnel
Wanneer een proxy op 127.0.0.1:8080 geen verkeer meer ontvangt, is een van drie dingen gebeurd: hij is nooit gestart, hij bond een andere poort, of het filter liet de loopback-verbinding vallen. De luisterende sockets opsommen beantwoordt dat met één commando, en toont ook welk proces de poort bezit wanneer twee tools het oneens zijn over wie eerst was.
Een lokaal adres in een route-opzoeking bevestigt hetzelfde vanaf de andere kant. ip route get tegen een loopback-bestemming rapporteert het loopback-apparaat, nooit de tunnel, wat een nuttige zin is om klaar te hebben wanneer iemand een routingwijziging als oplossing voorstelt.
De proxylaag: omgeving is geen configuratie
Veel zakelijke clients draaien een HTTP-proxy en verwachten dat applicaties die gebruiken. Het instellen van HTTPS_PROXY in een shell repareert commandoregeltools die hem respecteren, en doet niets voor een tool die zijn eigen instellingenbestand leest. Gradle, Selenium en gRPC raadplegen elk hun eigen configuratie, en een proxy die in één terminal is geëxporteerd is onzichtbaar voor een daemon die door de IDE is gestart.
Containertools zijn de gebruikelijke plek waar dit zichtbaar wordt. De loopback van een container is zijn eigen, dus 127.0.0.1 binnen de container betekent nooit de proxy van de host; het hostadres of een host-netwerkinstelling is nodig. Een oplossing die in de shell werkt en in de build faalt, is meestal deze rij, niet de tunnel.
De vertrouwenslaag: de tool leest een andere store
Interceptie is de tweede verandering, en die levert de meest misleidende fouten op. De client presenteert zijn eigen certificaat voor geïnspecteerde verbindingen, dus een browser die de bedrijfswortel vertrouwt slaagt, terwijl een tool met een meegeleverde CA-store faalt. Pythons requests via certifi is het klassieke geval: de store van het besturingssysteem kan correct zijn en het verzoek faalt toch, omdat die runtime hem nooit leest. De fouttekst noemt interceptie zelden, waardoor deze rij verkeerd wordt gediagnosticeerd als een kapot eindpunt.
Vergelijk wat het eindpunt werkelijk presenteert met wat de tool heeft gevalideerd. openssl s_client toont de keten die de server stuurde; de eigen validatie-uitvoer van de tool toont wat hij besloot. Als ze niet overeenkomen, REQUESTS_CA_BUNDLE of SSL_CERT_FILE is de hefboom voor die runtime, en de bedrijfswortel hoort in de store die die runtime leest, niet op een globale plek die slechts sommige tools respecteren.
Een versiewijziging die een SSL-fout oplost, is bewijs over vertrouwens- en cijferbeleid, niet over de VPN. Een Python-downgrade waardoor een SOAP-client werkt, veranderde de meegeleverde CA-store en de standaard-TLS-instellingen; het netwerkpad bewoog niet.
De filterlaag: ook die kan loopback laten vallen
De derde verandering is een packetfilter, en sommige producten installeren regels die verkeer laten vallen dat niet in de tunnel komt. Lokale listeners kunnen erbij horen. Dat maakt van een werkende socket een geweigerde of verlopen verbinding, en de resulterende fout lijkt op een bug in de applicatie in plaats van beleid op de machine.
Poortbezit is de andere helft van deze laag. BindException betekent dat de socket niet kon worden geopend, wat een andere fout is dan een geweigerde verbinding. Controleer of een ander proces de poort al heeft voordat je het filter de schuld geeft, zoek dan naar een regel die lokaal verkeer laat vallen en voeg de smalste toestemming toe die het product ondersteunt. Twee tools die om dezelfde debug-poort strijden, geven precies hetzelfde bericht als een beleidsblokkade, en slechts één ervan wordt door een firewallwijziging opgelost.
De debug-poort van Chrome faalt in dezelfde familie. De browser start, de driver bereikt het DevTools-eindpunt niet, en het bericht noemt DevTools in plaats van het netwerk. Extra startvlaggen en een overbodige drivermanager veranderen welk proces de poort bezit, waardoor het verwijderen ervan soms de VPN lijkt te repareren.
Repareer de laag die faalde
Repareer de laag die faalde, niet de tunnel. Een onbereikbare loopback-listener heeft correctie van zijn listener of zijn poort nodig. Een niet-vertrouwd certificaat heeft de bedrijfswortel nodig, geïnstalleerd waar die specifieke runtime kijkt, met de uitzondering smal gehouden. Een filter dat lokaal verkeer laat vallen heeft een specifieke toestemmingsregel nodig in plaats van een uitgeschakeld filter, want uitschakelen heropent ook alles wat het beschermde.
De VPN opnieuw verbinden test geen van deze lagen. Het voert alleen de wijziging opnieuw uit die ze brak, waardoor dezelfde drie fouten na elke herverbinding terugkomen en na elke herstart verdwijnen die de client inactief laat.