RFC 3261: Il DNA del VoIP – Capitolo 15
Autenticazione SIP Digest
Apriamo un tracciato pcap acquisito durante la registrazione di un telefono IP. Il primo messaggio è un REGISTER. Subito dopo compare una risposta 401 Unauthorized. A una lettura frettolosa sembra che il provider abbia rifiutato l’account: il codice appartiene alla classe 4xx e la parola Unauthorized fa pensare a una password errata.
Continuiamo però a seguire la sequenza. Il telefono invia un secondo REGISTER, questa volta con un header Authorization. Il registrar risponde 200 OK e la registrazione si conclude correttamente. In questo scenario il 401 non segnala un’anomalia: è la challenge di autenticazione che permette al server di chiedere al client una prova della conoscenza del segreto condiviso.
Nel Capitolo 14 abbiamo chiuso l’analisi delle risposte SIP, distinguendo gli errori riferiti a un server dagli insuccessi globali. Ora riprendiamo due risposte della classe 4xx già incontrate, 401 e 407, non per ripetere il catalogo dei codici ma per osservare il dialogo operativo che attivano. Vedremo chi invia la challenge, quali header devono essere abbinati, che cosa rappresentano realm e nonce, come nasce il valore response e perché la nuova richiesta non è una semplice ritrasmissione.
Quello che affrontiamo in questo capitolo è uno degli aspetti pratici più importanti che un tecnico VoIP deve assolutamente conoscere. L’autenticazione digest è alla base del protocooolo SIP e rappresenta il caso più frequente di richieata di assistenza per qualunque produttore o operatore nel mondo del VoIP.
Challenge: il termine che useremo
La sezione 22 della RFC 3261 adatta al SIP il modello di autenticazione HTTP. Per descriverlo useremo il termine originale challenge, che possiamo tradurre come “sfida di autenticazione”. Nel linguaggio tecnico inglese è però più preciso e immediatamente riconoscibile: indica il messaggio con cui il server fornisce al client i dati necessari per dimostrare di conoscere il segreto, senza inviare quel segreto nel messaggio SIP.
Il server non chiede normalmente al client di scrivere la password nella richiesta. Invia invece una challenge con alcuni parametri; il client combina metodo SIP, URI, nome utente, password e valori ricevuti per calcolare una risposta. D’ora in avanti useremo quindi challenge, evitando di alternarlo continuamente con la traduzione italiana.
“The framework for SIP authentication closely parallels that of HTTP.”
Il modello di autenticazione SIP segue da vicino quello di HTTP.
Questa frase della sezione 22.1 della RFC 3261 spiega l’origine dei nomi WWW-Authenticate e Authorization, che possono sorprendere in un tracciato telefonico. Non indicano che il telefono stia visitando una pagina web. Sono header adottati dal modello HTTP e impiegati nella segnalazione SIP.
La RFC 3261 vieta l’uso dello schema Basic nel SIP e definisce le regole per Digest nella sezione 22.4. L’idea pratica è semplice: entrambe le parti conoscono un segreto; il server fornisce una challenge; il client calcola un valore che il server può verificare. Nel messaggio viaggia il risultato del calcolo, non la password scritta in chiaro.
Autenticare e autorizzare restano due operazioni diverse. La prima verifica l’identità dichiarata, o almeno il possesso delle credenziali associate. La seconda stabilisce se quell’identità può compiere l’azione richiesta: registrare un contatto, originare una chiamata, raggiungere una destinazione internazionale o utilizzare un servizio. Credenziali valide non garantiscono quindi che ogni richiesta venga autorizzata.
401 e 407: due challenge diverse
La distinzione fondamentale riguarda l’elemento che chiede le credenziali. Un UAS o un registrar usa il 401; un proxy usa il 407. Le coppie corrette di risposta e header sono queste:
- 401 Unauthorized con
WWW-Authenticate; il client ripete la richiesta aggiungendoAuthorization. - 407 Proxy Authentication Required con
Proxy-Authenticate; il client ripete la richiesta aggiungendoProxy-Authorization.
La sezione 21.4.2 della RFC 3261 chiarisce che il 401 viene emesso da UAS e registrar, mentre il 407 è usato dai proxy. La sezione 21.4.8 descrive il 407. Questa non è una preferenza terminologica: usare la coppia sbagliata cambia il significato della challenge e può impedire al client di reagire correttamente.
Nelle reti reali un unico prodotto può svolgere più ruoli. Un PBX può agire da registrar verso i telefoni interni e da UAC verso il provider. Un SBC può terminare una richiesta in un caso e inoltrarla come proxy in un altro. Per interpretare 401 o 407 non basta quindi leggere il marchio dell’apparato: occorre capire quale ruolo logico sta svolgendo in quella specifica transazione.
Passaggio 1: il REGISTER iniziale
Immaginiamo che il telefono di Matteo debba registrare l’indirizzo 201 sul dominio pbx.example.it. Il primo REGISTER può essere inviato senza credenziali:
REGISTER sip:pbx.example.it SIP/2.0
Via: SIP/2.0/UDP 192.0.2.20:5060;branch=z9hG4bK-reg-001;rport
Max-Forwards: 70
From: "Matteo" <sip:201@pbx.example.it>;tag=matteo-01
To: "Matteo" <sip:201@pbx.example.it>
Call-ID: 8f3a21@192.0.2.20
CSeq: 1 REGISTER
Contact: <sip:201@192.0.2.20:5060>
Expires: 300
Content-Length: 0
La Request-Line identifica il registrar di destinazione. Via descrive il percorso della risposta e contiene il branch della transazione. From e To riportano l’identità SIP registrata, mentre Contact indica dove l’utente è raggiungibile. Il messaggio non contiene ancora Authorization.
Passaggio 2: la challenge 401
Il registrar non accetta subito la registrazione. Risponde con la challenge:
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.0.2.20:5060;branch=z9hG4bK-reg-001;received=198.51.100.24;rport=5060
From: "Matteo" <sip:201@pbx.example.it>;tag=matteo-01
To: "Matteo" <sip:201@pbx.example.it>;tag=registrar-77
Call-ID: 8f3a21@192.0.2.20
CSeq: 1 REGISTER
WWW-Authenticate: Digest realm="pbx.example.it",
nonce="a84f47e1c9b4432b",
algorithm=MD5,
qop="auth"
Content-Length: 0
La Status-Line contiene il 401. L’header WWW-Authenticate dichiara lo schema Digest e fornisce i parametri necessari. Il telefono non deve limitarsi a reinviare lo stesso pacchetto: deve costruire una nuova richiesta, calcolare la prova e incrementare CSeq.
Passaggio 3: leggere la challenge
Una challenge Digest contiene diversi elementi. Non tutti compaiono in ogni implementazione, ma alcuni sono indispensabili per capire il calcolo e per diagnosticare gli errori. Leggiamoli uno alla volta, senza confondere il loro ruolo.
realm identifica l’ambito amministrativo per il quale valgono le credenziali. Può coincidere con il dominio SIP, ma la coincidenza non è obbligatoria. Il client deve usare il realm ricevuto nella challenge, non ricavarlo liberamente dal campo From, dal dominio della Request-URI o dal nome del server configurato. Due piattaforme possono presentare realm diversi anche se appartengono alla stessa infrastruttura commerciale.
nonce significa number used once, cioè “numero usato una volta”. Il nome aiuta a ricordarne la funzione: è un valore generato dal server e inserito nella challenge per rendere il calcolo legato a quello specifico contesto. Il suo formato, la sua durata e i criteri con cui viene validato dipendono dal server.
Talvolta il nonce viene descritto in modo informale come una “chiave crittografica”, ma tecnicamente questa definizione non è corretta. La chiave segreta condivisa rimane la password; il nonce è invece un dato temporaneo che entra nel calcolo e contribuisce a impedire il riutilizzo indiscriminato di una vecchia risposta Digest. Il client non lo inventa, non lo decifra e non lo usa al posto della password: lo riceve dal server e lo restituisce, direttamente e attraverso il calcolo, nella nuova richiesta.
algorithm indica l’algoritmo richiesto. Nell’esempio compare MD5, coerente con il modello storico della RFC 3261. Le estensioni successive hanno introdotto algoritmi più moderni, ma un articolo dedicato alla RFC 3261 deve distinguere il comportamento originario dalle evoluzioni successive e dalle possibilità effettivamente supportate dai prodotti.
qop, cioè qualità della protezione, può proporre valori quali auth. Quando qop viene usato entrano nel calcolo anche cnonce, generato dal client, e nc, il contatore di utilizzo del nonce. Nell’esempio il valore 00000001 indica il primo uso di quel nonce in quel contesto.
opaque, quando presente, è un valore fornito dal server che il client deve restituire senza modificarlo. Serve al server per conservare informazioni associate alla challenge senza esporne necessariamente il significato al client.
Passaggio 4: il nuovo REGISTER
Dopo aver ricevuto la challenge, il telefono recupera il nome di autenticazione e il segreto configurati, usa i parametri ricevuti e invia una nuova richiesta:
REGISTER sip:pbx.example.it SIP/2.0
Via: SIP/2.0/UDP 192.0.2.20:5060;branch=z9hG4bK-reg-002;rport
Max-Forwards: 70
From: "Matteo" <sip:201@pbx.example.it>;tag=matteo-01
To: "Matteo" <sip:201@pbx.example.it>
Call-ID: 8f3a21@192.0.2.20
CSeq: 2 REGISTER
Contact: <sip:201@192.0.2.20:5060>
Expires: 300
Authorization: Digest username="201-auth",
realm="pbx.example.it",
nonce="a84f47e1c9b4432b",
uri="sip:pbx.example.it",
response="7c8d3b9ab15df21cf9a2a4c5b632e712",
algorithm=MD5,
qop=auth,
cnonce="31f2918b",
nc=00000001
Content-Length: 0
Il Call-ID resta lo stesso e consente di seguire il tentativo di registrazione. CSeq passa da 1 a 2, come richiede la sezione 22.2 della RFC 3261 quando il UAC ripresenta la richiesta dopo un 401 o un 407. Anche il branch di Via cambia, perché siamo davanti a una nuova transazione, non alla ritrasmissione del primo REGISTER.
L’header Authorization riporta il nome di autenticazione 201-auth. Questo valore può essere diverso dall’identità pubblica 201 scritta negli header From e To. Molti servizi distinguono infatti numero telefonico, URI SIP, account amministrativo e nome usato per l’autenticazione. Confonderli è una causa molto comune di registrazioni respinte.
Il valore response è il risultato del calcolo Digest. Non può essere confrontato visivamente con la password e non rimane necessariamente uguale tra due registrazioni: cambia se cambiano nonce, metodo, URI o altri parametri coinvolti. Incollare questo valore nel campo password di un telefono non ha alcun senso operativo.
Passaggio 5: calcolare response
Per comprendere il meccanismo non serve trasformare ogni analisi in un esercizio di crittografia, ma è utile conoscere la struttura logica del calcolo storico descritto dalla RFC. In forma semplificata, con algoritmo MD5 e qop impostato ad auth:
- HA1 deriva da username, realm e password;
- HA2 deriva dal metodo SIP e dalla URI indicata nelle credenziali;
- response combina HA1, nonce, contatore, cnonce, qop e HA2.
Una rappresentazione compatta è:
HA1 = MD5(username:realm:password)
HA2 = MD5(method:uri)
response = MD5(HA1:nonce:nc:cnonce:qop:HA2)
Se il client usa un realm diverso, calcola HA1 su dati differenti. Se usa INVITE al posto di REGISTER, cambia HA2. Se la URI usata per il calcolo non corrisponde al parametro uri trasmesso, il server otterrà un risultato diverso. Una sola differenza è sufficiente a far fallire la verifica.
Il server esegue il calcolo con i valori attesi e confronta il risultato con response. Se coincidono, la prova è valida; successivamente applica le proprie regole di autorizzazione. Se non coincidono, può ripetere la challenge o rifiutare la richiesta. La RFC stabilisce inoltre che il client non deve continuare a riprovare con credenziali appena rifiutate, salvo il caso in cui il nonce risulti scaduto.
⚠ I CONSIGLI DI VOIP.IT
Quando un account non si autentica, non fermarti alla parola Unauthorized. Confronta il realm ricevuto con quello effettivamente usato dal client, verifica il nome di autenticazione separatamente dal numero SIP e controlla che il secondo messaggio abbia CSeq e branch nuovi. Una sequenza continua di 401 non dimostra da sola che la password sia sbagliata: può dipendere anche da username, realm, URI, algoritmo, nonce scaduto o da una richiesta inviata all’apparato sbagliato.
La challenge 407 del proxy
Consideriamo ora una chiamata originata dal PBX verso il proxy del provider. Il PBX invia un INVITE e il proxy vuole autenticare l’origine prima di inoltrarlo. La sezione 22.3 della RFC 3261 assegna a questo caso la risposta 407.
SIP/2.0 407 Proxy Authentication Required
Via: SIP/2.0/UDP 203.0.113.10:5060;branch=z9hG4bK-inv-101
From: "Matteo" <sip:0551234567@voice.example.net>;tag=pbx-41
To: <sip:0212345678@voice.example.net>;tag=proxy-92
Call-ID: call-9941@203.0.113.10
CSeq: 40 INVITE
Proxy-Authenticate: Digest realm="voice.example.net",
nonce="b952ad0f8134e210",
algorithm=MD5,
qop="auth"
Content-Length: 0
Il PBX deve riconoscere Proxy-Authenticate e generare un nuovo INVITE contenente Proxy-Authorization. Le credenziali valgono per il realm del proxy che le ha richieste. In una catena con più proxy, un proxy il cui realm non corrisponde non deve consumare quelle credenziali.
Nel caso dell’INVITE c’è inoltre un dettaglio visibile nel tracciato: la risposta finale non positiva alla prima richiesta viene confermata con ACK secondo le regole della transazione INVITE. Successivamente il client genera il nuovo INVITE autenticato con CSeq incrementato. Non bisogna confondere l’ACK con il nuovo tentativo e non bisogna interpretare i due INVITE come semplici duplicati.
401 e 407 non appartengono solo al REGISTER
Nella pratica didattica 401 e REGISTER vengono spesso mostrati insieme perché costituiscono un esempio immediato. L’autenticazione Digest, però, può essere applicata anche ad altre richieste. Un provider può autenticare un INVITE; un server può richiedere credenziali per un’operazione diversa, in base alla propria architettura e alle proprie politiche.
Non esiste quindi un’associazione rigida del tipo “REGISTER uguale 401” e “INVITE uguale 407”. La risposta dipende dal ruolo del server che emette la challenge. Un registrar che autentica un REGISTER usa 401. Un UAS che autentica direttamente un INVITE può usare 401. Un proxy che autentica la stessa richiesta usa 407.
Anche l’invio preventivo delle credenziali può variare. Alcuni client conservano i parametri utili e aggiungono Authorization o Proxy-Authorization a richieste successive dello stesso contesto, riducendo il numero di scambi. Il server può comunque emettere una nuova challenge, per esempio se il nonce è scaduto. Le modalità di memorizzazione, la durata e le politiche operative dipendono dall’implementazione, entro i vincoli definiti dalla RFC.
Le chiamate entranti e uscenti si autenticano allo stesso modo?
Questa domanda compare spesso durante i corsi: se un PBX utilizza un trunk VoIP registrato, ogni chiamata deve superare una nuova autenticazione Digest, sia in uscita sia in ingresso? La risposta breve è normalmente no. Nei trunk basati su REGISTER, la prassi più comune tratta le due direzioni in modo diverso.
Partiamo da ciò che il PBX ha già fatto. Con il REGISTER ha comunicato al registrar del provider: “per raggiungere questo account SIP, in questo momento devi inviare le richieste a questo Contact”. Il registrar gli ha inviato una challenge 401, il PBX ha ripetuto il REGISTER con Authorization e il server ha verificato le credenziali. Il provider dispone quindi di un binding registrato, cioè dell’associazione fra l’identità SIP e la posizione corrente del PBX.
Quando arriva una chiamata destinata al numero del cliente, il provider consulta il proprio location service e inoltra l’INVITE verso il Contact registrato. Nella configurazione più comune, il PBX non risponde con una nuova challenge Digest all’INVITE entrante. Riconosce la richiesta perché proviene dall’infrastruttura del provider e perché raggiunge l’indirizzo reso disponibile dalla registrazione. Il controllo può basarsi sugli indirizzi IP autorizzati, sul trasporto utilizzato, sulla relazione con l’SBC o su altre regole configurate nel prodotto.
Occorre esprimere con precisione questa idea: il REGISTER autenticato non rende automaticamente autenticato, per magia, ogni INVITE futuro. La registrazione ha verificato il client che ha creato o aggiornato il binding; la chiamata entrante viene poi accettata secondo la relazione di fiducia e le politiche definite fra PBX e provider. La RFC non impone che tutti i sistemi funzionino in un solo modo. Alcune architetture possono applicare controlli ulteriori, usare TLS, autenticazione basata su certificati, liste di indirizzi oppure persino una challenge Digest anche in ingresso. Nei comuni trunk registrati, tuttavia, vedere un solo INVITE entrante senza Authorization è assolutamente normale.
Per le chiamate uscenti il comportamento abituale è diverso. Il PBX invia un INVITE al proxy del provider. Il proxy vuole verificare che quell’apparato possa utilizzare il trunk e originare la chiamata, quindi risponde spesso con 407 Proxy Authentication Required. Il PBX conferma la risposta finale con ACK e genera un nuovo INVITE contenente Proxy-Authorization. Se le credenziali sono corrette e la chiamata è autorizzata, il proxy prosegue l’elaborazione.
Nel tracciato si vedono quindi due INVITE. Questo passaggio appassiona perché rende visibile il protocollo mentre costruisce la fiducia: il primo INVITE dice che cosa il PBX vuole fare; il 407 chiede di dimostrare con quali credenziali può farlo; il secondo INVITE ripresenta la richiesta insieme alla prova Digest.
Non dobbiamo però chiamare il secondo messaggio “ritrasmissione”. Una ritrasmissione SIP ripete la stessa richiesta quando non è ancora arrivata una risposta e conserva lo stesso branch di Via e lo stesso CSeq. L’INVITE autenticato è invece una nuova richiesta e una nuova transazione:
- il valore numerico di CSeq aumenta;
- il branch di Via cambia;
- compare Proxy-Authorization, oppure Authorization nel caso di una challenge 401;
- realm, nonce e gli altri parametri devono corrispondere alla challenge ricevuta;
- il valore response viene calcolato usando il metodo INVITE e la URI prevista dal meccanismo Digest.
La sequenza tipica di una chiamata uscente può essere letta così:
PBX Proxy del provider
|--- INVITE, CSeq: 40 -------------------->|
|<-- 407 Proxy Authentication Required ---|
|--- ACK, CSeq: 40 ----------------------->|
|--- INVITE + Proxy-Authorization -------->|
| CSeq: 41, nuovo branch |
|<-- 100 Trying / 18x / risposta finale --|
L’ACK ha un ruolo preciso: chiude la prima transazione INVITE che ha ricevuto la risposta finale 407. Non contiene la nuova richiesta di chiamata e non sostituisce le credenziali. Solo dopo arriva il secondo INVITE autenticato.
Il procedimento osservato nel REGISTER è concettualmente molto simile:
PBX Registrar
|--- REGISTER, CSeq: 1 ------------------->|
|<-- 401 Unauthorized --------------------|
|--- REGISTER + Authorization ------------>|
| CSeq: 2, nuovo branch |
|<-- 200 OK ------------------------------|
REGISTER e INVITE: due Digest in parallelo
Mettiamo ora le due sequenze una accanto all’altra. Il meccanismo matematico non cambia: il server invia la challenge, il client usa le credenziali e i parametri ricevuti, quindi formula una nuova richiesta con il valore response. Cambiano invece lo scopo della richiesta, il ruolo del server, gli header utilizzati e ciò che accade dopo l’autenticazione.
Passaggio 1: la richiesta iniziale. Nel caso REGISTER, il PBX chiede al registrar di creare o aggiornare il binding tra l’identità SIP e il proprio Contact. Nel caso INVITE, il PBX chiede al proxy di avviare una chiamata verso una destinazione. Entrambe le prime richieste possono partire senza credenziali Digest, ma hanno obiettivi completamente diversi: la prima comunica la raggiungibilità, la seconda avvia una sessione.
Passaggio 2: la challenge. Il registrar risponde normalmente al REGISTER con 401 Unauthorized e inserisce WWW-Authenticate. Il proxy risponde normalmente all’INVITE uscente con 407 Proxy Authentication Required e inserisce Proxy-Authenticate. In entrambi i casi la risposta contiene realm, nonce e gli altri parametri necessari per il calcolo.
Passaggio 3: la nuova richiesta autenticata. Il PBX ricalcola response usando il metodo corretto. Per il REGISTER, HA2 contiene il metodo REGISTER e la nuova richiesta porta Authorization. Per la chiamata uscente, HA2 contiene il metodo INVITE e il nuovo INVITE porta Proxy-Authorization. In entrambi i flussi aumentano CSeq e cambia il branch di Via: non stiamo osservando una ritrasmissione, ma una nuova transazione.
Passaggio 4: l’esito. Se la Digest del REGISTER è corretta e la registrazione è autorizzata, il registrar risponde 200 OK e salva il binding. Se la Digest dell’INVITE è corretta e la chiamata è consentita, il proxy inizia a elaborarla e possiamo osservare 100 Trying, una risposta 18x e infine la risposta conclusiva. Credenziali valide non garantiscono che la chiamata venga accettata: una destinazione internazionale vietata dal profilo può essere rifiutata anche dopo un’autenticazione riuscita.
C’è infine una differenza che in Wireshark si vede immediatamente. Dopo la risposta finale 407 al primo INVITE, il PBX invia un ACK e solo successivamente genera il nuovo INVITE autenticato. Nel REGISTER questo passaggio non esiste: dopo il 401 viene costruito direttamente il nuovo REGISTER con Authorization. L’ACK non fa parte della Digest; appartiene alla gestione della transazione INVITE.
Anche qui la prima richiesta riceve una challenge e la seconda porta la prova Digest. Il ragionamento diagnostico rimane lo stesso: seguire il Call-ID, verificare l’incremento di CSeq, riconoscere il branch nuovo e controllare che l’header di autorizzazione corrisponda alla challenge. Il parallelismo consente a chi ha imparato a leggere la registrazione di affrontare il doppio INVITE senza ricominciare da zero.
Ti invito davvero a dedicare qualche minuto all’approfondimento VOIP.IT sulla Digest Authentication nei flussi REGISTER e INVITE. Le acquisizioni Wireshark mostrano le quattro fasi dei due procedimenti e rendono immediatamente visibile ciò che abbiamo appena messo in parallelo: prima richiesta senza credenziali, challenge 401 o 407, nuova richiesta con Authorization o Proxy-Authorization ed esito finale. È una lettura particolarmente utile da tenere aperta accanto a un proprio tracciato pcap, perché permette di allenare l’occhio e riconoscere la sequenza in pochi secondi. Questo capitolo completa poi quel percorso distinguendo autenticazione da autorizzazione, trunk registrati da peer statici e Digest da riconoscimento basato sull’indirizzo IP.
Possiamo quindi fissare una regola pratica, senza trasformarla in un obbligo universale: nel trunk registrato più comune, le chiamate uscenti ricevono spesso una challenge Digest, mentre quelle entranti vengono consegnate al Contact già registrato e accettate in base alla relazione di fiducia con il provider. Esistono eccezioni importanti. Un trunk autenticato per indirizzo IP può non mostrare alcun doppio INVITE in uscita; un client può inviare credenziali preventive; un PBX può inviare una challenge anche per richieste entranti; un SBC può applicare controlli differenti. Il tracciato pcap, letto insieme alla configurazione del servizio, ci dice quale modello è realmente in uso.
Nonce scaduto e nuovi tentativi
Il nonce non deve essere considerato eterno. Un server può rifiutare una prova costruita su un nonce non più valido e inviare una nuova challenge con il parametro stale=true. In questo caso il client non deve necessariamente chiedere una nuova password all’utente: può ripetere il calcolo usando il nuovo nonce e le credenziali già disponibili.
Questa distinzione è importante nella ricerca del guasto. Se il server dichiara stale, il problema riguarda la validità temporale o l’accettazione del nonce precedente. Se continua a inviare challenge senza stale dopo aver ricevuto una risposta, occorre verificare i valori usati nel calcolo. Se invece restituisce 403, le credenziali potrebbero essere state comprese ma la richiesta potrebbe non essere autorizzata, oppure il prodotto potrebbe utilizzare quel codice secondo la propria politica. Il significato va ricostruito osservando l’intera sequenza e la documentazione del servizio.
Digest non cifra il SIP e non protegge l’audio
Questo chiarimento è indispensabile: Digest non è cifratura del traffico. Evita normalmente di trasmettere la password in chiaro e fornisce una prova calcolata, ma gli header SIP restano leggibili in un’acquisizione effettuata lungo il percorso quando non si usa una protezione di trasporto. From, To, Contact, Call-ID, numeri chiamati e molti altri dati possono essere osservabili.
Digest non cifra neppure SDP, RTP o RTCP. Se un INVITE contiene un’offerta SDP, indirizzi, porte e codec rimangono esposti salvo l’impiego di meccanismi specifici. Il flusso audio segue un percorso distinto dalla segnalazione e richiede protezioni adatte, come SRTP in un’architettura correttamente configurata. TLS può proteggere la segnalazione su determinate tratte; non va però confuso con l’autenticazione Digest e non rende automaticamente cifrato il flusso audio.
Il modello storico basato su MD5 presenta inoltre limiti noti, soprattutto quando le password sono deboli e un attaccante può osservare una challenge e la relativa risposta. Il fatto che la password non compaia direttamente nel pacchetto non rende sicuro un segreto breve o prevedibile. Password robuste, limitazione dei tentativi, controllo degli accessi, trasporto protetto e algoritmi aggiornati devono far parte di una strategia complessiva.
Cosa guardare nel tracciato pcap
CONSIGLI PER WIRESHARK
Per isolare le challenge puoi usare il filtro sip.Status-Code == 401 || sip.Status-Code == 407. Poi amplia la vista alla conversazione SIP e correla i messaggi tramite Call-ID. Verifica la sequenza richiesta iniziale, challenge, nuova richiesta e risposta finale. Confronta CSeq e il parametro branch di Via: nella nuova richiesta autenticata devono cambiare; una ritrasmissione mantiene invece gli elementi identificativi della stessa transazione. Controlla infine la coppia di header: 401 con WWW-Authenticate e Authorization, 407 con Proxy-Authenticate e Proxy-Authorization. Nel menu Telefonia, per REGISTER e altri scambi non legati a una chiamata usa la vista dei flussi SIP; la vista Chiamate VoIP potrebbe non rappresentare tutto ciò che serve.
Per una diagnosi ordinata conviene poi confrontare questi valori:
- realm nella challenge e nelle credenziali;
- nonce ricevuto e quello restituito;
- username usato per autenticarsi, senza dedurlo automaticamente da From;
- uri presente nell’header di autorizzazione;
- metodo indicato nella Request-Line e in CSeq;
- qop, cnonce e nc, quando richiesti;
- algorithm proposto dal server e supportato dal client;
- eventuale stale=true in una nuova challenge.
Wireshark mostra il valore response ma, senza conoscere il segreto e tutti i parametri corretti, non può dichiarare semplicemente quale password fosse configurata. Il tracciato permette però di riconoscere incoerenze, challenge ripetute, realm inattesi, richieste non ripresentate e differenze tra la sequenza corretta e una vera anomalia.
Errori frequenti in PBX, telefoni e trunk
Interpretare il primo 401 come fallimento. Se dopo il 401 arriva una nuova richiesta autenticata e poi un 200 OK, il comportamento è normale. Nei sistemi di monitoraggio conviene valutare l’esito della sequenza, non contare ogni 401 come allarme.
Configurare il numero nel campo sbagliato. Numero pubblico, interno, Auth ID e username Digest possono essere valori diversi. L’interfaccia del prodotto può usare etichette non uniformi: “User ID”, “Authentication user”, “Account” o “SIP username”. Bisogna ricondurre ogni campo al parametro realmente inviato.
Forzare il realm. Alcuni apparati permettono di configurarlo manualmente; altri usano quello ricevuto. Se il valore imposto non coincide con la challenge, il calcolo fallisce. Prima di modificare il PBX bisogna leggere il WWW-Authenticate o Proxy-Authenticate effettivamente ricevuto.
Riutilizzare una vecchia challenge. Dopo un riavvio, una variazione di nodo o una scadenza, il server può generare un nonce differente. Il client deve reagire alla nuova challenge. Cache difettose, apparati intermedi o implementazioni non compatibili possono produrre cicli di autenticazione.
Confondere autenticazione IP e Digest. L’assenza di 401 o 407 non indica automaticamente una carenza. Il trunk potrebbe utilizzare un’autenticazione basata sull’indirizzo IP e appartenere quindi a una tipologia diversa da quella studiata finora. Nel paragrafo finale distingueremo con precisione i due modelli.
Ignorare NAT e instradamento. Le credenziali possono essere corrette ma la nuova richiesta può non raggiungere lo stesso nodo, oppure la risposta può tornare su un percorso diverso. Prima di attribuire tutto alla password occorre controllare indirizzi, porte, DNS, bilanciamento, firewall e comportamento dell’SBC.
Provare all’infinito. Un telefono o PBX che continua a inviare richieste con credenziali respinte crea traffico inutile, può attivare sistemi di difesa e rende il tracciato più difficile da leggere. Occorre distinguere una nuova challenge valida da un ciclo causato da configurazione errata.
Un metodo pratico di diagnosi
Quando un telefono non si registra o una chiamata autenticata non parte, procediamo dal comportamento osservabile. Prima verifichiamo se il server risponde. Poi identifichiamo 401 o 407 e controlliamo l’header della challenge. Successivamente cerchiamo la nuova richiesta e osserviamo se contiene l’header corretto. Solo dopo confrontiamo i parametri Digest e l’esito finale.
Se manca del tutto la seconda richiesta, il client potrebbe non avere credenziali, non riconoscere l’algoritmo, non associare il realm a un account o non gestire la challenge ricevuta. Se la seconda richiesta esiste ma riceve ancora 401 o 407, si passa a username, realm, URI, nonce, qop, algoritmo e password. Se arriva un 403, si valuta anche l’autorizzazione e la politica del servizio. Se arriva 200 OK, la procedura Digest ha avuto successo anche se il log conserva il primo 401.
Nei sistemi con più nodi va controllato che la challenge e la verifica siano coerenti. Un bilanciatore può consegnare la seconda richiesta a un server diverso; questo è perfettamente gestibile se i nodi condividono le informazioni necessarie o costruiscono nonce verificabili da tutto il gruppo. Se non lo fanno, il client può apparire intrappolato in una serie di challenge pur usando credenziali corrette.
Vademecum della Digest che non funziona
Quando l’autenticazione non si conclude, la sequenza dei messaggi fornisce quasi sempre un primo indizio. Questo piccolo vademecum che deriva dall’esperienza pratica, raccoglie le casistiche più comuni e aiuta a capire dove indirizzare subito il controllo.
- Il client riceve 401 o 407, ma non invia una seconda richiesta. Probabilmente non ha credenziali configurate, non riconosce il realm, non supporta l’algoritmo proposto oppure non associa la challenge all’account corretto. Verificare che il prodotto abbia compilato Auth ID e password e che gestisca gli header WWW-Authenticate o Proxy-Authenticate ricevuti.
- La seconda richiesta contiene Authorization, ma arriva un nuovo 401. Nei casi più comuni username o password sono errati. Controllare il nome di autenticazione, che può essere diverso dal numero telefonico, dall’interno e dal valore scritto nel From. Verificare inoltre che non siano presenti spazi, caratteri copiati per errore o una password precedente rimasta nella configurazione.
- La seconda richiesta contiene Proxy-Authorization, ma arriva ancora 407. Le credenziali fornite al proxy non sono state accettate. Oltre a username e password, confrontare realm, nonce, URI, qop, algoritmo, cnonce e nc. Una differenza in uno solo di questi valori modifica response.
- Il realm inviato dal client non corrisponde a quello della challenge. Il calcolo HA1 cambia e la verifica non può riuscire. Il client deve usare il realm ricevuto dal server. Non bisogna dedurlo automaticamente dal dominio SIP, dal Request-URI o dal nome commerciale del provider.
- Il server invia una nuova challenge con stale=true. Il nonce precedente è scaduto o non è più valido. Il client dovrebbe ripetere il calcolo con il nuovo nonce senza chiedere necessariamente nuove credenziali. Se non lo fa, verificare la gestione della cache Digest e la compatibilità del firmware.
- Il server propone un algoritmo o un qop non gestito dal client. Il telefono o il PBX può non riuscire a costruire Authorization. Confrontare algorithm e qop offerti nella challenge con quelli supportati dal prodotto. Non forzare MD5 o un altro algoritmo senza verificare le possibilità ammesse dal servizio.
- Il secondo messaggio sembra identico al primo. Controllare CSeq e branch di Via. La richiesta autenticata deve appartenere a una nuova transazione: CSeq aumenta e il branch cambia. Se entrambi restano uguali, potremmo osservare una ritrasmissione, non il nuovo tentativo con credenziali.
- La Digest riesce, ma la chiamata riceve 403 Forbidden. Non è necessariamente un errore di autenticazione. L’identità può essere stata riconosciuta, ma la destinazione non è autorizzata: chiamate internazionali, numerazioni premium, CLI non ammesso, credito insufficiente, limiti contrattuali o account sospeso sono casi tipici. Qui occorre verificare il profilo di servizio e le politiche del provider.
- La registrazione termina con 200 OK, ma l’INVITE uscente riceve 403. Il REGISTER dimostra che le credenziali di registrazione sono state accettate; non dimostra che il cliente possa originare qualunque chiamata. Controllare permessi, formato della numerazione, identità presentata nel From o nel P-Asserted-Identity e regole del piano telefonico.
- Le credenziali sono corrette, ma le challenge continuano alternandosi. In un’infrastruttura con bilanciamento, la seconda richiesta potrebbe raggiungere un nodo che non riconosce il nonce generato dal primo. Confrontare indirizzi IP, Record-Route, percorso SIP e comportamento dell’SBC. Il problema può trovarsi nella coerenza del gruppo di server, non nel PBX.
- Non compare alcuna challenge, ma il trunk funziona. Potrebbe trattarsi di un trunk con autenticazione basata sull’indirizzo IP o di credenziali inviate preventivamente. Prima di cercare un 401 o un 407 che non arriverà, verificare il tipo di trunk previsto dal provider.
- Non compare alcuna challenge e il server non risponde. Questo non è ancora un problema Digest. Controllare prima DNS, indirizzo e porta di destinazione, trasporto UDP o TCP, firewall, NAT, routing e raggiungibilità dell’SBC. L’autenticazione può iniziare soltanto dopo che la richiesta ha raggiunto il server.
La lettura corretta segue quindi un ordine semplice: prima verifichiamo la raggiungibilità, poi la presenza della challenge, quindi la costruzione della seconda richiesta e infine l’autorizzazione del servizio richiesto. In questo modo evitiamo di attribuire alla password qualsiasi chiamata rifiutata.
Non tutti i trunk SIP usano Digest
Arrivati alla fine dell’analisi, dobbiamo evitare una conclusione troppo sbrigativa: non tutti gli account e non tutti i trunk SIP forniti dagli operatori utilizzano Digest. La modalità dipende dal servizio, dall’architettura del provider e dal contratto tecnico previsto per il cliente. Nella pratica incontriamo soprattutto due tipologie.
Trunk SIP con autenticazione Digest, in inglese Digest-authenticated SIP trunk. Il PBX dispone di username e password e dimostra di conoscere il segreto attraverso il meccanismo challenge-response. Molti servizi di questa categoria utilizzano anche il REGISTER: il PBX registra il proprio Contact e rende nota al provider la posizione alla quale consegnare le chiamate entranti. Per le chiamate uscenti può poi ricevere una challenge 407 o, secondo il ruolo dell’elemento remoto, una challenge 401.
La presenza del REGISTER e l’uso di Digest sono concetti collegati molto spesso, ma non sono sinonimi. REGISTER svolge la funzione di location service: crea o aggiorna il binding tra identità SIP e Contact. Digest svolge la funzione di autenticazione: permette di verificare le credenziali del client. Un’implementazione può combinarli, ma le due funzioni devono rimanere distinte nella nostra lettura.
Trunk SIP con autenticazione basata sull’indirizzo IP, in inglese IP-authenticated SIP trunk o IP-based authenticated trunk. In molti PBX e SBC viene configurato anche come static peer o, più semplicemente, peer SIP statico. Provider e cliente dichiarano preventivamente gli indirizzi IP dai quali accetteranno la segnalazione. Il provider riconosce il PBX dall’IP sorgente autorizzato; il PBX, a sua volta, accetta le richieste provenienti dagli indirizzi del provider configurati come peer affidabili.
In questo secondo modello si parla spesso di riconoscimento IP reciproco. Il termine descrive bene la relazione operativa, ma va interpretato correttamente: non esiste un header SIP chiamato “peer authentication”. Il controllo viene eseguito dagli apparati confrontando indirizzo sorgente, trasporto, porta e regole locali con gli elementi autorizzati. L’espressione peer trunk appartiene soprattutto al linguaggio dei PBX e degli SBC; il nome tecnico del criterio di autenticazione è autenticazione basata sull’indirizzo IP.
Un trunk IP-authenticated normalmente non ha bisogno di inviare REGISTER per comunicare una posizione variabile: gli estremi sono configurati staticamente e devono essere raggiungibili agli indirizzi concordati. Allo stesso modo, una chiamata uscente può essere accettata senza 401, senza 407 e senza un secondo INVITE, perché l’indirizzo IP sorgente è già autorizzato. Anche le chiamate entranti vengono riconosciute dal PBX in base al peer remoto configurato.
Questo modello richiede indirizzi stabili e regole di rete molto curate. NAT, variazioni dell’IP pubblico, apparati non autorizzati che riescono a usare un indirizzo ammesso o configurazioni troppo estese delle liste di accesso possono compromettere il servizio o ridurne la sicurezza. Per questo l’autenticazione IP viene spesso affiancata da VPN, collegamenti privati, TLS, SBC e filtri di rete. Digest e riconoscimento IP possono inoltre essere combinati: non sono necessariamente alternative assolute.
Il tracciato pcap permette di riconoscere rapidamente il modello in uso. Se osserviamo REGISTER o INVITE, risposta 401 o 407 e nuova richiesta con Authorization o Proxy-Authorization, siamo davanti a un processo di autenticazione Digest. Se la prima richiesta viene elaborata direttamente e gli apparati sono configurati come peer statici con indirizzi autorizzati, siamo probabilmente davanti a un trunk con autenticazione IP. La conferma definitiva deve sempre arrivare dalla configurazione del PBX, dell’SBC e dal profilo tecnico comunicato dal provider.
Dalla prova d’identità al trasporto
L’autenticazione SIP Digest è un meccanismo di challenge e risposta. Il 401 abbina WWW-Authenticate ad Authorization per UAS e registrar; il 407 abbina Proxy-Authenticate a Proxy-Authorization per il proxy. Realm definisce l’ambito delle credenziali, nonce lega il calcolo alla challenge del server e response dimostra la conoscenza del segreto senza trasmetterlo direttamente.
Nel tracciato pcap la sequenza corretta è leggibile: richiesta iniziale, challenge, nuova richiesta con CSeq incrementato e nuovo branch, quindi risposta finale. Questa lettura evita di classificare ogni 401 come errore e permette di separare una normale negoziazione da credenziali realmente respinte.
Resta però un confine netto: Digest non cifra la segnalazione e non protegge i flussi multimediali. Nel prossimo capitolo analizzeremo proprio come i messaggi SIP viaggiano su UDP e TCP, come vengono delimitati, quali effetti produce la loro dimensione e dove si colloca TLS nella protezione del trasporto.
