TLS 1.3 invia ancora il nome del server in chiaro
TLS 1.3 cifra l’handshake ma non lo SNI. Leggete il ClientHello, verificate una vera accettazione ECH e registrate ciò che un osservatore può ancora vedere.
Aggiornare un listener a TLS 1.3 cambia ciò che un osservatore può leggere, ma non quanto suggerisce il numero di versione. Il ClientHello viaggia ancora prima che venga negoziata qualsiasi cifratura, e in una connessione ordinaria il nome del server richiesto sta lì in chiaro. Encrypted Client Hello è il meccanismo che lo nasconde, ed è un impiego separato con i propri prerequisiti. Eseguite questi quattro passaggi prima di scrivere una politica che presupponga l’uno o l’altro comportamento.
Che cosa espone davvero l’handshake
TLS 1.3 cifra il certificato del server e la maggior parte dell’handshake che segue il ServerHello. Tutto ciò che il client invia per primo resta fuori da quella protezione, perché le chiavi non esistono ancora. L’indicazione del nome del server fa parte di quel primo volo, ed è per questo che un osservatore passivo può ancora leggerla senza rompere nulla.
La specificazione ECH, RFC 9849, cambia questo cifrando un ClientHello interno per un server che collabora. L’handshake esterno rimane e porta un nome pubblico che la rete può vedere, quindi l’impiego ha ancora bisogno di un’identità esterna che abbia senso per gli intermediari. Quel nome esterno è la parte che le persone trascurano quando si aspettano che la connessione diventi anonima. È un nome di copertura, non un nome nascosto, e deve risolversi e autenticarsi come qualsiasi altro.
Niente di tutto questo nasconde il percorso di consegna. Gli indirizzi di origine e destinazione, le porte, le dimensioni dei pacchetti e i tempi restano osservabili, e spesso dicono più su chi parla di quanto faccia il nome. La risoluzione dei nomi e le relazioni a livello applicativo sono un altro strato ancora, ciascuno con la propria visibilità.
Leggere un ClientHello invece di supporre
La versione nel ServerHello non vi dice che cosa ha inviato il client. Guardate il primo volo direttamente, da una posizione che rappresenti l’osservatore che vi interessa.
openssl s_client -connect app.plant.example:443 -servername app.plant.example -tls1_3 </dev/null> 2>/dev/null | head -20 sudo tcpdump -ni eth0 -c 40 'tcp port 443' -w /tmp/tls.pcap tshark -r /tmp/tls.pcap -Y 'tls.handshake.extensions_server_name' -T fields -e tls.handshake.extensions_server_name
Il primo comando esegue un handshake e mostra i parametri negoziati, inclusa la versione del protocollo e il nome che avete richiesto. Il secondo cattura i primi pacchetti di una connessione reale, e il terzo estrae il campo SNI da quella cattura. Se il campo è popolato, l’osservatore che avete emulato può leggerlo.
Catturate separatamente sul lato client e sul percorso quando i due non concordano, perché una cattura locale può mostrare un nome che un middlebox in seguito riscrive o scarta. Catturate anche da un host che non termina TLS da solo, dato che un proxy che termina vede il chiaro per progetto e non dimostra nulla su ciò che vede la rete.
Trattare un’estensione ECH come un’affermazione, non come una prova
Vedere un’estensione ECH in un ClientHello non significa che la connessione abbia usato ECH. I client inviano GREASE ECH quando non hanno una configurazione utilizzabile, proprio perché i loro handshake appaiano uniformi. L’estensione è presente, il hello interno è un’esca, e il nome reale è ancora leggibile.
dig +short HTTPS app.plant.example openssl s_client -connect app.plant.example:443 -tls1_3 -status </dev/null> 2>/dev/null | grep -i -E 'ech|status_request'
Il primo comando mostra se l’origine pubblica un record di risorsa HTTPS con un parametro di configurazione ECH, ed è così che i client apprendono la chiave. Il secondo cerca informazioni di stato dell’handshake, anche se il messaggio di successo di un client è la prova più solida. L’accettazione è ciò che conta: un server che non possiede la chiave corrispondente non può decifrare il hello interno, e la connessione ripiega.
Controllate anche il client, poiché il supporto dei browser e la configurazione variano per versione e piattaforma. Una politica costruita su «i browser moderni usano ECH» è una congettura su una flotta, non un fatto sulla vostra flotta. Inventariate le versioni che si connettono davvero, poi provatene una per ciascuna. La stessa pagina che funziona da un browser desktop aggiornato può non nascondere nulla a un client più vecchio sulla stessa rete.
Scrivere nella politica l’ambito dell’osservatore
Indicate dove si trova l’osservatore e che cosa è visibile in quel punto prima di decidere su che cosa può contare un controllo. La connessione di un browser a un sito, un trasporto VPN esterno e un proxy che termina TLS espongono ciascuno un insieme diverso di fatti, e una regola scritta per una posizione raramente si trasferisce in modo pulito a un’altra.
Se un controllo dipende dalla lettura dello SNI, provate come si comportano i client distribuiti quando ECH è disponibile e quando non lo è. Poi registrate la conseguenza sulla compatibilità, perché un filtro che smette silenziosamente di corrispondere è peggio di uno che non è mai stato distribuito.
Infine, mantenete l’incertezza nel verbale. Sostituire una vecchia affermazione universale con una più nuova lascia lo stesso vuoto sotto un altro nome di protocollo, e il prossimo revisore ci crederà con la stessa fermezza.