Il mio portatile diceva connesso. Il client di AWS Client VPN mostrava il suo stato verde, l’endpoint registrava una sessione e io non riuscivo comunque ad aprire una porta MongoDB su un’istanza EC2 in una sottorete privata. Niente era palesemente rotto: il certificato era valido, il profilo veniva dalla console e il tunnel trasportava traffico. L’errore era mio, perché leggevo connesso come autorizzato.

L’accesso risponde a una sola domanda: questa identità può stabilire una sessione? Tutto ciò che segue lo decidono regole separate che non vedono mai il tuo certificato. Una sessione che si autentica e un pacchetto che arriva sono due successi diversi, e lo scarto fra i due è dove vivono la maggior parte delle segnalazioni del tipo la VPN è su ma l’host non è raggiungibile.

I controlli qui sotto sono l’ordine che uso adesso.

Che cosa dimostra davvero una sessione connessa

Durante l’handshake l’endpoint convalida il certificato del client contro il proprio trust store, oppure reindirizza il browser al tuo provider di identità quando SAML è configurato. Se questo passa, il client riceve un indirizzo dal CIDR client dell’endpoint e la console mostra una connessione attiva. In nessun momento di quello scambio qualcosa chiede se puoi raggiungere 10.0.4.17 sulla porta 27017.

Il permesso verso una destinazione è un oggetto separato sull’endpoint. Ogni flusso viene confrontato con le regole di autorizzazione, e ciascuna abbina un CIDR di destinazione al gruppo a cui la regola è concessa. Quando nessuna regola copre la destinazione, l’endpoint accetta la sessione e scarta il traffico. Non c’è banner, non c’è ciclo di riconnessione e non c’è nulla nell’interfaccia del client che dica negato.

Confronta la regola di autorizzazione con la risorsa, non con la VPC

Elenca le regole e mettile accanto all’indirizzo che l’istanza ha davvero:

aws ec2 describe-client-vpn-authorization-rules \
  --client-vpn-endpoint-id cvpn-endpoint-0a1b2c3d4e5f6a7b8

L’output mostra un CIDR di destinazione e un ID di gruppo per regola. Ci sono due guasti nascosti. La regola può autorizzare 10.0.0.0/16 mentre l’istanza sta in una VPC in peering su 10.1.0.0/16; la rotta di peering esiste, ma nessuno ha scritto una regola di autorizzazione per il secondo intervallo. Oppure la regola punta a un gruppo di directory a cui l’utente appartiene nella directory ma non nel gruppo che l’endpoint valuta.

Scrivi la regola più stretta che copre la destinazione, e aggiungine una seconda solo quando un secondo CIDR serve davvero. Una regola ampia 0.0.0.0/0 presa da un avvio rapido funziona, ed è per questo che sopravvive in produzione e nasconde il modello.

Due tabelle di routing decidono se il pacchetto si muove

Una rotta dell’endpoint mappa un CIDR di destinazione su una delle sottoreti a cui l’endpoint è associato. È metà del percorso. La tabella di routing della sottorete deve comunque sapere come inoltrare il pacchetto, e questo conta nel momento in cui la destinazione è dietro una connessione di peering, un transit gateway o un intervallo on-premises raggiungibile via tunnel site-to-site.

aws ec2 describe-client-vpn-routes \
  --client-vpn-endpoint-id cvpn-endpoint-0a1b2c3d4e5f6a7b8

Cerca una rotta la cui destinazione corrisponda al CIDR della risorsa e il cui target sia una sottorete associata. Se la rotta manca, aggiungila. Se c’è e l’host resta muto, lo scarto è lato VPC, quindi confronta con la tabella di routing della sottorete di associazione.

Un’impostazione lato client rompe il routing senza rompere il tunnel: un profilo che contiene route-nopull. La direttiva dice a un client basato su OpenVPN di ignorare le rotte che il server spinge, così l’interfaccia sale solo con l’indirizzo dell’endpoint e la destinazione semplicemente non ha rotta. Controlla con ip route show su Linux o netstat -rn su macOS se esiste una rotta attraverso l’interfaccia tun. Se non c’è, togli route-nopull dal profilo esportato e riconnettiti perché le rotte spinte vengano applicate.

I gruppi di sicurezza non vedono l’indirizzo del tuo client

Questa è la parte che ho sbagliato per un intero pomeriggio. Per un endpoint IPv4 associato a una sottorete, il servizio traduce l’indirizzo di origine del client nell’indirizzo dell’interfaccia di rete dell’endpoint in quella sottorete. Il pacchetto che arriva all’istanza non porta l’indirizzo che il tuo client mostrava, quindi una regola di gruppo di sicurezza che consente il pool dei client, diciamo 172.16.0.0/22, non corrisponde a niente.

Consenti la porta dal gruppo di sicurezza dell’endpoint, che è agganciato all’interfaccia dell’associazione, invece che dal CIDR client. Fare riferimento al gruppo è più durevole che codificare un indirizzo a mano, perché l’indirizzo dell’interfaccia non è tuo da controllare. Le ACL di rete sono senza stato, quindi dove esistono voci personalizzate sia la direzione in ingresso sia quella in uscita devono consentire il flusso.

Connettiti anche all’indirizzo privato dell’istanza. Un IP pubblico porta il pacchetto fuori dalla VPC e lo riporta dentro per un’altra strada con altre regole, quindi un test sull’indirizzo pubblico non dice nulla sul percorso privato.

Un ordine di isolamento che si ferma al primo guasto

Percorri questi punti in ordine e fermati dove uno fallisce. Ogni passo esclude uno strato invece di tutti.

  1. Conferma quale identità ha usato la sessione e quale gruppo valuta l’endpoint. Un certificato da un trust store non è lo stesso principal di un’asserzione SAML dalla directory.
  2. Conferma che una regola di autorizzazione copra il CIDR della risorsa per quel gruppo.
  3. Conferma che esista una rotta dell’endpoint e che punti a una sottorete associata, poi che la tabella di routing della sottorete possa inoltrare oltre.
  4. Conferma che il gruppo di sicurezza consenta la porta dall’interfaccia dell’endpoint e non dal pool dei client.
  5. Prova dall’interno della VPC, con una sessione SSM su un’altra istanza nella stessa sottorete, per separare un problema applicativo da un problema del percorso client.

Quando i passi non sono decisivi, questa tabella è ciò su cui mi appoggio:

SymptomLayer to inspect
Client shows connected, host times out, no byte growth on the interfaceAuthorization rule, then security group
Ping fails but a TCP connect to the port succeedsICMP is blocked; not an access failure
Tunnel reconnects every few minutesTwo machines sharing one client certificate
Works on one laptop, fails on anotherLocal profile has route-nopull or stale pushed routes

Due dettagli dell’account producono sintomi che sembrano errori di permesso. Ogni utente ha bisogno di un certificato client distinto; condividerne uno fra due macchine fa sì che le sessioni si spostino a vicenda, e il risultato è un ciclo di riconnessione invece di un rifiuto. Quando si crea un nuovo endpoint, la console mostra un nome DNS che alcune versioni del client accettano solo con il prefisso casuale mostrato nella pagina dell’endpoint, quindi copia il nome completo invece di ricostruirlo.

Se il quinto passo ti blocca, scarica il registro delle connessioni dell’endpoint e leggi le voci di autorizzazione prima di cambiare qualcosa. Il registro nomina la destinazione controllata e la regola che ha corrisposto o no, e questo riduce la domanda a quattro strati a una sola risposta.

Articoli correlati