Stagione 94 / Episodio 3
I cancelli e la vedetta
Come due pari nascosti dietro router e firewall trovano una strada: NAT e i suoi comportamenti, i candidati ICE, i server STUN, i controlli di connettività, la raccolta progressiva dei candidati e il riavvio di ICE.
Note dell'episodio
Bentornati sulle due rive. Nell'episodio scorso le due rive si sono scambiate il progetto del ponte. Oggi affrontiamo il problema più concreto di tutti: le mura.
Quasi nessuna delle due rive è aperta sul fiume. Ognuna sta dietro a mura con dei cancelli, e i guardiani dei cancelli hanno regole precise su chi può entrare. Trovare un varco tra due città murate, senza che nessuna delle due apra le porte a chiunque, è il lavoro di un procedimento chiamato ICE.
Partiamo da cosa sono queste mura.
Il vostro computer di casa, il vostro telefono, il portatile in ufficio quasi sicuramente non hanno un indirizzo pubblico su internet. Hanno un indirizzo privato, del tipo centonovantadue punto centosessantotto, valido solo dentro la rete locale. Quando escono verso internet, il router traduce quell'indirizzo nel proprio indirizzo pubblico. Questa traduzione si chiama NAT, traduzione degli indirizzi di rete.
Il NAT funziona come un guardiano che annota chi esce. Quando il vostro computer manda un pacchetto verso un server, il guardiano scrive sul registro: il computer numero venti è uscito dalla porta cinquantunomila verso quel server. Quando la risposta torna, il guardiano controlla il registro e la fa entrare. Ma se arriva un pacchetto che nessuno ha chiesto, il guardiano lo scarta.
Ed ecco il problema di WebRTC. Se due rive sono entrambe dietro a un NAT, nessuna delle due può ricevere un pacchetto dall'altra, perché nessuna delle due ha invitato l'altra per prima. Due città con i cancelli chiusi, in cui ogni guardiano aspetta che sia l'altro ad aprire.
Su larga scala il problema è ancora più marcato. Molti operatori mobili, e sempre più operatori fissi, usano un NAT ulteriore, condiviso tra migliaia di clienti. Mura dentro altre mura.
Non tutti i guardiani si comportano allo stesso modo.
Il comportamento più amichevole è questo: una volta che il vostro computer è uscito dalla porta cinquantunomila, il guardiano usa la stessa porta pubblica qualunque sia la destinazione. In termini tecnici, la mappatura è indipendente dall'indirizzo di destinazione. È il caso più comune nei router di casa, ed è quello che permette a WebRTC di funzionare quasi sempre.
Il comportamento più ostile, spesso chiamato NAT simmetrico, usa invece una porta pubblica diversa per ogni destinazione. Quello che la vedetta vi dice sulla vostra porta pubblica vale solo per la vedetta stessa, non per l'altra riva. In questo caso un varco diretto, molto spesso, non si trova. Si trova nelle reti aziendali, in alcuni operatori mobili, nelle reti degli alberghi. E in quel caso serve il traghetto, che vedremo nel prossimo episodio.
Come fa una riva a sapere come la vede il mondo esterno?
Sale sulla torre e chiede a una vedetta. La vedetta è un server STUN, descritto nella RFC 8489. Il funzionamento è di una semplicità disarmante: il browser manda una richiesta al server STUN, e il server risponde dicendo da quale indirizzo e da quale porta ha visto arrivare la richiesta. Tutto qui. È come chiedere a qualcuno fuori dalle mura: scusi, da quale cancello sono uscito?
Questa informazione è preziosa, perché è l'indirizzo che l'altra riva dovrà usare per raggiungervi. I server STUN sono leggerissimi, non trasportano nessun dato della chiamata, e ce ne sono di pubblici e gratuiti. Quello di Google, per esempio, è usato in migliaia di esempi in rete. Per un'applicazione in produzione, però, conviene averne uno proprio: costa pochissimo e non dipendete da un servizio senza garanzie.
Con le informazioni della vedetta, il browser compone una lista di candidati: tutti i punti da cui la riva potrebbe essere raggiunta. Ogni candidato è un indirizzo con una porta, e appartiene a uno di questi tipi.
I candidati host sono gli indirizzi delle schede di rete del dispositivo. Funzionano se le due rive stanno nella stessa rete locale. I candidati server reflexive sono gli indirizzi pubblici scoperti dalla vedetta STUN. Funzionano attraverso i NAT amichevoli. I candidati relay sono gli indirizzi del traghetto, il server TURN. Funzionano quasi sempre, ma passano da un intermediario. Esiste infine un quarto tipo, peer reflexive, scoperto durante i controlli stessi.
Ogni candidato ha una priorità, calcolata con una formula precisa. In parole semplici: si preferisce il candidato più diretto. Host prima di tutti, poi i peer reflexive, poi i server reflexive, e il relay per ultimo.
Una volta che le due rive si sono scambiate le liste di candidati, con il messaggero, comincia la prova.
ICE forma tutte le coppie possibili: un mio candidato con un tuo candidato. Le ordina per priorità, e per ognuna manda un piccolo pacchetto di prova, una richiesta STUN diretta all'altra riva, firmata con le credenziali che erano scritte nell'SDP. Se la risposta torna, quella coppia funziona.
Il trucco geniale sta qui. Quando la mia riva manda una prova verso il cancello dell'altra, il mio guardiano annota l'uscita. Se nello stesso momento l'altra riva manda una prova verso il mio cancello, il mio guardiano la fa entrare, perché pensa che sia la risposta. I due cancelli si aprono a vicenda, per un attimo, perché entrambi i guardiani credono di aver invitato l'altro. Questa tecnica si chiama perforazione del NAT, e ICE la fa in modo sistematico.
Delle due rive, una ha il ruolo di controllore. Quando ha trovato una coppia che funziona, la nomina: d'ora in poi il ponte passa da qui. ICE continua poi a mandare piccole prove periodiche, per tenere aperti i cancelli: i guardiani dimenticano in fretta.
Raccogliere tutti i candidati può richiedere tempo, soprattutto il relay, che richiede un dialogo con il server TURN.
Per questo esiste trickle ICE, descritto nella RFC 8838: invece di aspettare la lista completa, il browser vi consegna i candidati uno alla volta, con l'evento icecandidate, e voi li mandate subito all'altra riva. Le prove cominciano mentre la raccolta è ancora in corso. La chiamata parte molto prima.
C'è poi un dettaglio di riservatezza. Pubblicare l'indirizzo privato del vostro computer a una pagina web qualsiasi era un modo per tracciare le persone. Per questo i browser, se la pagina non ha ancora il permesso di usare microfono o videocamera, sostituiscono l'indirizzo host con un nome casuale che finisce in punto local, risolto con mDNS solo dentro la rete locale. Se nei vostri log vedete questi nomi strani, non è un errore.
Una chiamata può durare un'ora, e in un'ora un telefono passa dal wifi alla rete mobile.
Lo stato della connessione si legge in due proprietà, iceConnectionState e connectionState. Disconnected significa che le prove periodiche non tornano: potrebbe essere un problema passeggero. Failed significa che non c'è più nessuna strada. In quel caso la cura si chiama riavvio di ICE: chiamate restartIce, il browser raccoglie nuovi candidati, e la trattativa riparte senza abbattere il ponte.
Quindi, ricapitolando: le due rive stanno dietro a mura chiamate NAT, la vedetta STUN dice a ognuna come la vede il mondo, ICE raccoglie i candidati, li prova a coppie e nomina il guado migliore, aprendo i cancelli dall'interno.
Ma a volte il guado non c'è proprio: mura troppo alte, firewall che lasciano passare solo il traffico web. Allora serve una barca vera, che porti tutto il carico. Nel prossimo episodio parliamo del traghetto. Ci sentiamo lì.