mitmproxy, DevTools, Gradle: tre livelli dietro la VPN
Il loopback non entra mai nel tunnel. Classificate il sintomo come listener, archivio di fiducia o filtro dei pacchetti, e riparate il livello che ha davvero fallito.
La VPN si connette, e tre strumenti senza rapporto falliscono in tre modi diversi lo stesso pomeriggio. mitmproxy smette di vedere richieste, Chrome rifiuta il debugger e Gradle lancia BindException mentre collega un socket locale. Il sospetto condiviso è che il tunnel blocchi localhost. Non può: 127.0.0.1 viene gestito dentro il kernel e non raggiunge mai un adattatore, figuriamoci un gateway.
Tre livelli, tre guasti diversi
Ciò che è cambiato con il client non è la rotta verso il loopback. Sono un proxy locale, un archivio di fiducia della macchina e un filtro dei pacchetti, e ciascuno rompe una parte diversa del flusso di lavoro di uno sviluppatore. Collocare il sintomo nella riga giusta è gran parte della diagnosi:
| 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? |
Quasi ogni rapporto di questo tipo parte dall'ultima riga e risale, il che è al contrario. Il tunnel è l'unico livello che dimostrabilmente non può vedere il traffico di loopback, quindi merita il minimo sospetto. Iniziate da ciò che il processo ha collegato, poi chiedete a quali certificati si fida, e solo dopo guardate la politica sulla macchina.
Iniziate dal listener, non dal tunnel
Quando un proxy su 127.0.0.1:8080 smette di ricevere traffico, è successa una di tre cose: non è mai partito, ha collegato un'altra porta, o il filtro ha scartato la connessione di loopback. Elencare i socket in ascolto risponde con un solo comando, e mostra anche quale processo possiede la porta quando due strumenti non concordano su chi sia arrivato prima.
Un indirizzo locale in una ricerca di rotta conferma la stessa cosa dalla direzione opposta. ip route get verso una destinazione loopback riporta il dispositivo loopback, mai il tunnel, che è una frase utile da tenere pronta quando qualcuno propone un cambio di routing come soluzione.
Il livello proxy: l'ambiente non è configurazione
Molti client aziendali eseguono un proxy HTTP e si aspettano che le applicazioni lo usino. Impostare HTTPS_PROXY in una shell corregge gli strumenti da riga di comando che lo rispettano, e non fa nulla per uno strumento che legge il proprio file di impostazioni. Gradle, Selenium e gRPC consultano ciascuno la propria configurazione, e un proxy esportato in un terminale è invisibile a un demone avviato dall'IDE.
Gli strumenti per container sono il luogo abituale in cui questo diventa visibile. Il loopback di un container è il suo, quindi 127.0.0.1 dentro il container non significa mai il proxy dell'host; servono l'indirizzo dell'host o un'impostazione di rete dell'host. Una correzione che funziona nella shell e fallisce nella build è di solito questa riga, non il tunnel.
Il livello di fiducia: lo strumento legge un altro archivio
L'intercettazione è il secondo cambiamento, e produce gli errori più fuorvianti. Il client presenta il proprio certificato per le connessioni ispezionate, quindi un browser che si fida della radice aziendale riesce mentre uno strumento con un archivio CA incluso fallisce. Le requests di Python tramite certifi sono il caso classico: l'archivio del sistema operativo può essere corretto e la richiesta fallisce comunque, perché quell'ambiente di esecuzione non lo legge mai. Il testo dell'errore menziona raramente l'intercettazione, ed è per questo che questa riga viene diagnosticata male come endpoint rotto.
Confrontate ciò che l'endpoint presenta davvero con ciò che lo strumento ha validato. openssl s_client mostra la catena inviata dal server; l'output di validazione dello strumento mostra cosa ha deciso. Quando non concordano, REQUESTS_CA_BUNDLE o SSL_CERT_FILE è la leva per quell'ambiente di esecuzione, e la radice aziendale appartiene all'archivio che quell'ambiente legge, non a una posizione globale che solo alcuni strumenti rispettano.
Un cambio di versione che corregge un errore SSL è una prova sulla politica di fiducia e di cifratura, non sulla VPN. Un downgrade di Python che fa funzionare un client SOAP ha cambiato l'archivio CA incluso e le impostazioni TLS predefinite; il percorso di rete non si è mosso.
Il livello del filtro: può scartare anche il loopback
Il terzo cambiamento è un filtro dei pacchetti, e alcuni prodotti installano regole che scartano il traffico che non entra nel tunnel. I listener locali possono essere inclusi. Questo trasforma un socket funzionante in una connessione rifiutata o scaduta, e l'errore risultante sembra un bug dell'applicazione più che una politica della macchina.
La proprietà della porta è l'altra metà di questo livello. BindException significa che il socket non è stato aperto, il che è un guasto diverso da una connessione rifiutata. Verificate se un altro processo detiene già la porta prima di dare la colpa al filtro, poi cercate una regola che scarti il traffico locale e aggiungete il permesso più stretto che il prodotto supporta. Due strumenti che competono per la stessa porta di debug producono esattamente lo stesso messaggio di un blocco di politica, e solo uno dei due si corregge con un cambio di firewall.
La porta di debug di Chrome fallisce nella stessa famiglia. Il browser si avvia, il driver non raggiunge l'endpoint DevTools, e il messaggio nomina DevTools invece della rete. Flag di avvio aggiuntivi e un gestore di driver ridondante cambiano quale processo possiede la porta, ed è per questo che rimuoverli a volte sembra riparare la VPN.
Riparate il livello che ha fallito
Riparate il livello che ha fallito, non il tunnel. Un listener loopback irraggiungibile ha bisogno che il suo listener o la sua porta siano corretti. Un certificato non affidabile ha bisogno della radice aziendale installata dove guarda quello specifico ambiente di esecuzione, con l'eccezione tenuta stretta. Un filtro che scarta il traffico locale ha bisogno di una regola di permesso specifica invece di un filtro disattivato, perché disattivarlo riapre anche tutto il resto che proteggeva.
Riconnettere la VPN non verifica nessuno di questi livelli. Esegue di nuovo solo il cambiamento che li ha rotti, ed è per questo che gli stessi tre guasti tornano dopo ogni riconnessione e spariscono dopo ogni riavvio che lascia inattivo il client.