Tesi di specializzazione

Note sui virus trojan e worm.

 download file completo, stampabile formato doc

 ISSEA s.a.

Istituto Superiore Studi di Economia Aziendale

POLITECNICO di STUDI AZIENDALI - Lugano (CH)

 

Facoltà di Scienze Aziendali

Specializzazione: Informatica industriale applicata alla robotica

DOTTORATO DI SPECIALIZZAZIONE

 

Titolo della tesi:

IMPLEMENTAZIONE DI PROGRAMMI “TSR” E CONSIDERAZIONE SUL LORO UTILIZZO ILLEGALE A SCOPO DI SPIONAGGIO INDUSTRIALE.

 

dottorando  di specializzazione:  dott. MARCO GOTTARDO

matricola n° 965/02

 Relatore Dott. Zecchinato Beniamino

  

Anno accademico 2001/2002 - sessione d'esame del 17 Giugno 2002

 

Avvertenza: La presente tesi di specializzazione appartiene in tutte le sue parti al “Politecnico degli studi aziendali di Lugano” compresi i codici sorgente i manuali d’uso e i contenuti tecnici allegati. Si diffida espressamente chiunque all’utilizzazione dei codici sorgenti per la creazione l’utilizzo e la diffusione degli eseguibili ottenibili dalla compilazione dei suddetti codici.

I codici risultano redatti e depositati in territorio Svizzero e quindi non assoggettabili alla legislatura italiana.

Si ricorda che l’intrusione informatica in Italia è un reato penale, e che la creazione e diffusione di programmi classificati come virus è un reato perseguibile penalmente.  

Alcune routine della presente tesi necessiteranno di notevoli nozioni di programmazione per poter funzionare in modo da poter sgravare l’autore da possibili implicazioni legali dovuto a l’uso/abuso dei presenti codici senza preventiva autorizzazione.

 

Cap.1      Introduzione.

Definizione.

Definiamo come virus un programma o applicativo in grado di eseguirsi ed eventualmente installarsi senza lo specifico consenso dell’operatore.

Esistono una moltitudine di programmi e suite aventi questa proprietà pur non essendo stati pensati espressamente per essere dei virus.

Nella storia dei computer si sono susseguite diverse generazioni di virus che sostanzialmente seguivano l’evoluzione dei sistemi operativi a che erano destinati a colpire.

 

Prima generazione di virus

I programmi virus destinati a colpire il glorioso “Microsoft Disk operation system” noto come MS-DOS erano per lo più dei TSR, ovvero residenti in memoria RAM e pienamente cooperante con i task attivi.

I programmi di tipo TSR agiscono direttamente sugli interruput e quindi vengono esguiti in back ground senza disturbare il processo in corso, un pò come agisce, tanto per fare un esempio, il driver del mouse.

I danni software derivati dalla presenza dei Virus di vecchia generazione erano ingenti, mentre quelli hardware erano spesso solo simulati.

La virulenza di questi “animaletti” era elevatissima quindi la loro presenza nel sistema una volta finita la fase di latenza era immediatamente rilevata.

I target (obbiettivi da colpire) erano solitamente i programmi con estensione .exe, .com, oppure il MBR (master boot record, che contiene la traccia zero dell’H.D.), o distruggevano la FAT ( tabella di allocazione dei file rendendo inutilizzabile tutto il contenuto dell’H.D.   

 

Seconda generazione di virus. 

Nella seconda generazione cambia il modo di agire, gli effetti e i target, si tende a rimanere nello stato di latenza e ad essere non virulenti (cioè a non clonare il virus in modo che sia più difficilmente rilevabile).

Gli scopi sono più diretti all’intrusione informatica, lo spionaggio e il furto di documenti, tanto che sono stati scritti appositi articoli di legge basati sulla “violazione di domicilio”  per i quali sono previste sanzioni penali emesse per la prima volta nel gennaio 2002 a carico di un gruppo di Hacker colpevoli di avere attaccato una istituzione privata.

Una delle caratteristiche salienti dei nuovi virus è l’opzione conosciuta come  Stealth  la quale è una tecnologia software che fornisce al programma TSR l’abilità di lanciarsi automaticamente e in maniera del tutto “invisibile” anche da un controllore di task attivi.

Gli esempi più eclatanti di Stealth sono il virus “brain” il quale su richiesta doll’operatore di mostrare il contenuto e l’attivazione attuale del settore di boot (settore di avvio) mostra l’mmagine dell’originale e non quello attualmente in uso.

Un altro virus molto “simpatico” è il Frodo che ad una richiesta di scansione antivirus era in grado di auto disinfettarsi per poi ritornare attivo alla chiusura del file rendendosi praticamente inrilevabile.

La richiesta di proprietà del file sospetto infetto viene soddisfatta da un’immagine fittizia che riporta la corretta lunghezza in Kbyte e il fatto che “non è stato recentemente modificato”.

Un virus con questa opzione può comunque rendere instabile il file infetto che delle volte presenta un crasch (si blocca).

La tecnologia Stealth crea delle chiavi sul registro di windows che in fase di Boot vengono lette ed eseguite con la conseguenza che una ben definita area di memoria RAM viene riservata all’applicativo ospite tramite la chiamata di un file eseguibile che si trova nelle directory protette del sistema operativo.

Si ricorda che Windows nasconde le cartelle di sistema ponendo l’under score (lineetta bassa) davanti al nome della cartella stessa, e che un file lanciato in memoria facente parte del sistema non può essere rimosso durante la fase runtime (di esecuzione).

Un virus che ha lo scopo di rallentare la macchina infetta è Whale il quale impiega la tecnologia Stealth in maniera un po’ diversa, infatti è in grado di cambiare la propria criptatura e la chiave con cui viene gestito dal sistema operativo. Ad ogni sezione di windows esso sceglie una criptatura da un set random (casuale) quindi non distinguibile direttamente dai sistemi antivirus.

 

Trojan e worms

Gli ultimi sviluppi informatici hanno portato alla produzione di programmi molto maliziosi che sfruttano la labilità dei sistemi basati su windows anche se aventi file system NT.

Da quanto stiamo per dirvi potrete dedurre da soli che non esiste alcuna sicurezza per i vostri dati se il vostro PC è basato su windows…quindi se i vostri sistemi montano questi file system Condoglianze! Perché per voi non esistono sistemi sicuri con cui difendervi.

Da alcuni anni a scopo di ribellione nei confronti dell’egemonia di alcune note aziende produttrici di Software, e al fine di impedirne il monopolio di mercato, un gruppo di studenti e di affermati ingegneri provenienti da svariate parti del mondo, spesso elogiati e spesso dannati dalle recensioni mondiali hanno fondato quella che può essere considerata una vera e propria setta “nota agli enti governativi e investigativi internazionali con il nome culto della mucca morta “ il cui scopo è anche quello di Sfida contro i propri limiti e dimostrazione al mondo delle proprie capacità.

I prodotti di questa “loggia” di solito fanno parte del progetto GNU che mette a disposizione software e progetti open source a libera distribuzione come avviene ad esempio per Linux e cose analoghe.

Ciò che spinge questo gruppo di persone nella loro attività è il concetto che il software come altri rami della cultura sono patrimonio dell’umanità e quindi devono essere di pubblico dominio ed utilizzo….ovviamente ciò contrasta con gli interessi di tutte le aziende private che lavorano con un naturale scopo di lucro.

Di notevole interesse è il convegno annuale mondiale denominato DEFCON # giunto alla settima edizione in cui i migliori programmatori del mondo hanno la possibilità di confrontarsi presentando nuove idee e risultati.

Spesso queste persone, o almeno una buona parte di essi, amano autodefinirsi “Hackers”e non di rado vengo contatti da aziende o uffici governativi al fine di testare la sicurezza delle loro fortezze informatiche….spesso miseramente scardinate al grido di “Camelot è caduta !”

L’idea basilare di un virus “Trojano” sta nel nasconderlo all’interno di un file vettore che a differenza di altri può essere anche diverso da un eseguibile, ad esempio un’immagine .gif e un documento word.

Analogamente alla famosa vicenda secondo cui i soldati si nascosero all’interno di un cavallo di legno al fine di oltrepassare le mura della città di Troia il virus sotto esame si nasconde nel codice del file vettore di natura qualsiasi e supera il muro di fuoco “firewall” che rappresenta la vostra protezione dall’area internet…una volta dentro non c’è scampo…se il cavallo si apre i soldati metteranno a ferro e fuoco la vostra città o meglio il vostro dominio.

La meschinità di questo fatto sta nel caso che di solito vi viene presentato il file infetto come un “regalo” da parte di un amico esattamente come accadde ai troiani, quindi diffidate nella maniera più assoluta di qualsiasi cosa che vi venga allegata da persone di cui non siete assolutamente certi della loro lealtà nei vostri confronti….anche se il “regalino” non risulta essere un programma con estensione .exe

Un virus di tipo Trojan comunque si muove per definizione a bordo di un vettore e quindi deve essere abbinato a un protocollo FTP  (files tranfert protocols ), molto spesso si diffonde con gli allegati della posta elettronica.

L’unica maniera per provare l’esistenza di un troiano all’interno di un file è quello di procedere al disassemblaggio del medesimo, ma questo è solitamente impraticabile da un programmatore che sia poco più che principiante, figuriamoci quindi da un mero utente dei software commerciali.

I programmi antivirus sono basati su algoritmi di tipo VCRC (Cyclic Redundancy Codes for any file and validation data) che cercano all’interno del codice eseguibile delle stringe note, non compatibili con il tipo di file vettore e che abbiano corrispondenza con quelle memorizzate in data base a corredo.

È di facile comprensione il fatto che variare alcune ricorrenze nel codice sorgente prima di assemblarlo rende il prodotto finale Polimorfo, ovvero irriconoscibile dall’antivirus perché non più corrispondente alle ricorrenze a data base.

 

Worm

Questo tipo di Virus ha un comportamento ancora piu infame del Trojan visto che per la sua diffusione  utilizza i protocolli http, o irc (internet real chat), pertanto non ha bisogno di alcun vettore per il trasporto.Il caso più eclatante si ebbe nel 1998 quando internet negli stati uniti dovette subire una momentanea disconnessione a causa di “the Internet Worm” che aveva scoperto una falla nel sistema di protocolli Unix sendmail e il “Finger”, che come tutti i programmatori navigati sanno serve a vedere se un utente in internet sta attualmente utilizzando il protocollo TCP-IP ovvero se sta navigando o comunque è connesso.

 

Scopo principale di un trojan

Lo scopo principale come già accennato non è quello di devastare le installazioni software di un personal computer come facevano i virus di prima generazione, ma quello di avere uno strumento di amministrazione remota per macchine Windows 95/98 in grado di dare addirittura più accesso e controllo dell’operatore seduto davanti al pc.

Il programma consente, ad esempio, di accedere via Internet o rete locale a un computer remoto, sul quale permette di esaminare e modificare il contenuto di file e directory, visualizzare ciò che c'è sullo schermo, modificare il Registro, telecomandare mouse e tastiera e molto altro.

Come avrete intuito, è uno strumento estremamente utile per chi deve fare la manutenzione di macchine Windows e vuole evitare di doversi recare fisicamente sul posto. La possibilità di telecomandare  mouse e tastiera consente di mostrare all'utente l'esatta procedura da seguire o addirittura eseguirla per lui.

Quanto esposto nel seguito deve essere considerato un virus dato che può essere configurato e installato su un computer senza il consenso dell’utente con semplici espedienti (che non troverete qui).

Il trojan può monitorare l'attività di un utente (arrivando ad accendergli microfono e Webcam) senza segnalare in alcun modo che è in corso un monitoraggio. Di conseguenza si presta ad alcuni usi molto scorretti, come ad esempio l'intrusione informatica.

 

Cap. 2     Suite di Amministrazione remota.

Basi di amministrazione remota.

 Introduciamo ora la terminologia di base utile per la comprensione della tesi.

Un Trojan generalmente è composto da due parti: un programma client e un programma server.

La prima parte va installata sulla macchina dell'amministratore (chi vuole prendere il controllo); la seconda va installata sul computer da amministrare.

Per analogia, i due computer sono chiamati rispettivamente macchina client (quella dell'amministratore) e macchina server (quella da amministrare).

Questa situazione può creare inizialmente un po' di ambiguità lessicale, infatti solitamente un server ha un ruolo dominante e attivo e il client si limita a ricevere il prodotto e le istruzioni del server. Nel caso del Trojan in questione, invece, è il client che comanda il server invertendo un po’ la situazione classica.

Nella trattazione useremo la seguente convenzione:

·         macchina client = macchina dell'amministratore

·         macchina server = macchina da amministrare

·         amministratore = operatore che assume il controllo.

 

La suite di programmi si compone di tre file:

·         Pok_client= Strumento da installare in locale ad uso dell’amministratore.

·         Pok_config = Configuratore del software Server.

·         Pok.exe = Server da istallare nella macchina da controllare

                                               

fig.1  Icone scelte per la suit di programmi che compongono il virus Pok.

Configurazione del Server:

Al fine di poter telecontrollare in maniera univoca il computer su cui è installato il server è necessario riconoscerlo senza ambiguità tra i milioni di PC che in ogni istante condividono la rete delle reti (internet).

Il programma server va configurato prima di essere installato sul PC da amministrare. Questa configurazione si fa sulla macchina client (quella dell'amministratore), usando l’apposito programma pok_config.exe.

Configurare il programma server

1.        Per prima cosa, si esegua una copia del file Pok_Server.exe e rinomirla usando un nome intuitivo (ad esempio, se andrà installata su un computer affidato a una persona che si chiama Anna, potreste chiamarlo Anna.exe; in questo esempio, visto che la macchina da amministrare è un laptop Sony , la copia si chiamerà Sony.exe).
Lasciare intatta l'estensione .exe.

                                                       fig.2 Il server standard viene rinominato Anna.exe oppure Sony.exe o altro nome qualsiasi.

         Si noti che durante questa fase le icone di lancio del Server  compaiono nella versione Standard.

2.        Avviare Pok_cfg.exe e scegliere il file .exe che si intende configurare (in questo caso, quindi, Sony.exe).

fig.3 Con un doppio Click sull’icona di Pok_config si apre il Form sovrastante.

Ora è necessario aprire un server di Pok agendo sul tasto “Apri Server”, ovviamente viene proposta la possibilità di spostarsi tra le cartelle nella maniera classica di windows.Una volta caricato il Server nella casella “Opzioni Variabili” compariranno le varianti minime configurabili come ad esempio l’attivazione della modalità Stealth che comprendl’opzione “insidius mode” e Startup.  Fig. 4 Aspetto del programma di configurazione di Pok, opzioni base.

3.        Nella schermata dedicata al tipo di rete (Network type), accettare il default (TCPIO).

fig.5 Selezione del protocollo di comunicazione Internet.

4.        Scegliere la porta sulla quale si intende attivare la comunicazione fra programma client e programma server. Come dice il programma, è meglio usare un valore superiore a 1024 per evitare conflitti. Le istruzioni originali di Pok usano come esempio la porta 18006.

fig. 6 Selezione della porta di accesso al computer Server.

5.        Scegliere l'algoritmo di cifratura che si vole usare (probabilmente potrete usare soltanto quello XOR, se non si è residenti negli Stati Uniti).

fig. 7 Algoritmo di cifratura standard

6.        Digitare una parola chiave (password) che servirà a garantire che solo chi la conosce potrà effettuare amministrazione remota sulla macchina sulla quale verrà installato il programma server che stiamo configurando. Per comodità di questo esempio, supponete che la password sia il classico, intramontabile pippo.

 fig 8 Password

7.        Cliccate su Uscita,  il server è pronto per essere installato.

Abbiamo visto come tutti i parametri configurabili del programma server Pok sono elencati nella struttura a cartelle nell'angolo in basso a sinistra, ed è qui che si viene per modificarli. Ad esempio, la porta di comunicazione è indicata nella cartella Startup alla voce Init Cmd Bind Str.

 

Configurazione della modalità “Spionaggio”

Per default, il programma server Pok è configurato in modo che sia necessario avviarlo manualmente ogni volta sulla macchina da amministrare. Se c’è l’intenzione di farlo avviare  automaticamente ogni volta che viene acceso il computer da amministrare, dovete attivare il parametro Stealth > Run at startup. Usate quest'opzione con un po' di buonsenso e non abusatene.

 

fig.9 Settaggio del Server per avvio automatico in fase Bootstrap di windows

 

Una cosa fondamentale per una spia è l’eliminazione delle tracce del suo passaggio, per fare questo è sufficiente abilitare la seconda voce nella lista della cartella Stealth, “Delete original file”, così facendo una volta mandato in esecuzione il Server esso apporterà le dovute modifiche al registro di windows per poi autodistruggersi in maniera permante senza ovviamente passare per il cestino.

L’opzione “Runtime pathname” consente al server di istallare il suo nucleo nella cartella di sistema con un nome a scelta, un utente malizioso farà in modo di farlo sembrare il piu’ possibile ad un file standard di Windows.

Se oltre alla malizia ci si vuole mettere anche un pò di cattiveria si può optare per JDBGMGR il quale è un file utilissimo ma non indispensabile al sistema operativo (si tratta del Java Bebuger che consente e monitorizza l’esecuzione delle Applet, in modo particolare durante la navigazione internet).

Usando JDBGMGR si sovrascrive questo file di sistema distruggendolo, l’utente un po’ ingenuo non capirà come mai alcuni siti web non vengono visualizzati correttamente e difficilmente sarà in grado di ripristinare la mormale funzionalità di sistema.

Si vuole fare notare che quella allegata alla presente Tesi è l’unica copia esistente del Trojan Pok ( nome che deriva dall’Ungherese   “Ragno” , che con aria minacciosa insidia la rete)  pertanto il nucleo risulta sconosciuto agli attuali Software Antivirus.

Il file che si vuole sostituire ha l’icona rappresentata in figura.e qualunque utente esperto, o quasi, di windows ne conosce posizione, e funzionalità, quindi non procederebbe mai alla rimozione manuale.

 

 

fig.10 File di sistema che si consiglia di colpire per occultare al meglio il Trojan.

 

In caso di fallimento della rimozione del Server con le tecniche previste in Pok Client.

Supponiamo che per un qualsiasi motivo non ben definito non si riesca piu a rimuovere il Server dal computer di chi ha subito la nostra intrusione.

È ovvio che bisogna escogitare un sistema che ci consenta di “fare sparire” la prova del reato commesso  cautelandoci da eventuali ritorsioni legali.

Una tecnica vergognosamente subdola potrebbe essere la seguente: (si ricorda lo scopo puramente accademico della tesi e che chiunque è diffidato dalla messa in opera).

·         Fate appoggio ad un ISP (internet server provider) che metta a disposizione il servizio di mail anonimo.

·         Inviare una mail spacciandovi per il gestore Internet a cui si collega la persona che avete colpito, ( se siete riusciti a telecontrollare il suo computer allora di certo sapete  a che ISP si collega.

·         Inviate una mail spacciandovi per l’amministartore del server con il seguente testo o analogo:  Servizio antivirus Online, siamo spiacenti di comunicare ai nostri utenti che una momentanea sconnessione del servizio di protezione del nostro server potrebbe avere causato l’infezione di alcuni nostri clienti con un nuovo virus.

Si chiede la collaborazione dei gentili clienti per l’autorilevazione dello stesso, si tratta di un virus a lungo periodo di latenza circa 14 giorni, una volta esploso distrugge la FAT del sistema rendendolo inutilizzabile.

Si prega di procedere come segue:  Avviare il cerca File di windows e inserire la ricerca per jdbgmgr.exe , se viene rilevato un file che mostra l’icona a forma di orsetto non apritelo per nessun motivo! Cancellatelo immediatamente.     Si ringrazia per la collaborazione.  (Vedi nota n° 1 Appendice “Implicazioni legali”).

(Vedi nota n° 1 Appendice “Implicazioni legali”).

 

Opzione Hide process.

Alcuni sistemi operativi mettono a dispozione dei tools che consentono di visualizzare i task attivi, il loro nome e la loro posizione. Abilitando la funzione Hide process il Server attivo non sarà  visualizzabile neppure da questi programmi anche se appositamente studiati.

 

Opzioni  Host process name e Service Name (NT).                                                                                     

Quando il server è installato ed attivo l’aministratore potrà rintracciare la sua creatura utilizzando i nomi inseriti in questi campi.

Nel sistema NT ad esempio si consiglia ( e viene anche proposto come default) il nome Remote Administration Service.

Una volta apportate tutte le modifiche desiderate al programma server salvare cliccando su Salva Server. Chiudere il programma di configurazione, oppure cliccare su Chiudi Server (altrimenti non potrete copiare correttamente il file del programma server e otterrete un errore di condivisione se cercate di farlo via rete locale). A questo punto il programma server è pronto per essere installato sulla macchina da amministrare.

 

Versioni di Windows telecontrollabili.

Il programma server funziona soltanto con Windows 95 OSR2, Windows 98 e Windows NT. Il sistema non è stato testato su Windows 98 Seconda Edizione, Windows ME e Windows 2000, e dubito fortemente che funzioni con Windows XP per il quale sarà necessaria una modifica ai sorgenti.

 

 

Installare Pok_Server sul PC da amministrare (macchina remota)

 

Attenzione: prima di installare Pok_Server sul PC Target (la macchina remota), è bene essere al corrente di  come si disinstalla e quali modifiche apporta al sistema operativo: I dettagli si trovano più avanti in questa Tesi.

E' altamente consigliabile, soprattutto a chi è cosciente di non essere molto ferrato sull’utilizzo del PC, di  effettuare un backup completo.

Il programma server “Pok_Server.exe” va configurato prima di essere installato sul PC remoto da amministrare. Questa configurazione si fa sulla macchina client (quella dell'amministratore), usando il programma Pok_config.exe nella maniera già esposta..

Installazione vera e propria del programma server

L'installazione vera e propria è molto banale: si tratta soltanto di copiare il file del programma server (Sony.exe, i questa esposizione) alla macchina da amministrare ed eseguirlo sulla macchina stessa.

L'esecuzione è molto rapida e non visualizza praticamente nulla sullo schermo (neppure un messaggio di conferma). Al termine di questa operazione, la macchina da amministrare è pronta per l'amministrazione remota. Non occorre riavviare Windows sulla macchina da amministrare.

Se avete impostato il programma server in modo che si avvii automaticamente, lo farà ogni volta che il computer da amministrare riavvia Windows.

Nota bene che non c’è nessun sintomo visibile della presenza in esecuzione del nostro Server, sarà quindi inutile andare a cercarlo nella barra dei programmi attivi di windows (vicino all’orologio) ed in molti casi riesce anche ad eludere appositi strumenti di sorveglianzadi tipo “process viewer”.

L’utente malizioso scoprirà da solo svariate tecniche per far pervenire il Server ad utenti non propriamente consenzienti, ma ovviamente in questa sede si diffida questi dal farlo.

Si consiglia vivamente di consultare in appendice  i risvolti legali della questione.

 

Che cosa fa esattamente Pok_Server quando si installa sulla macchina server?

·         Scrive nella cartella system di Windows (per Windows 95/98) o nella cartella system32 (per Windows NT) un file che per default si chiama umgr32.exe. Il nome, tuttavia, può essere modificato, come già visto, durante la configurazione del programma server.

·         Se è stato impostato l'avvio automatico, modifica il Registro di Windows della macchina da amministrare, in modo da avviarsi automaticamente e senza segnalazioni ogni volta che l'utente avvia Windows.

Collegarsi alla macchina da amministrare

 

L'esempio che segue si basa su due macchine collegate in una elementare rete locale ethernet. Gli indirizzi IP citati nel seguito rispecchiano questa situazione. Prima di fare esperimenti via Internet, si consiglia di provare su una piccola rete locale: soprattutto, è bene fare gli esperimenti collegando due vostri computer.

L'amministrazione remota via Internet ha ulteriori problemi e requisiti che non ho ancora approfondito e che verranno trattati più avanti: tanto per farne due esempi, l'amministrazione via Internet richiede ovviamente che la macchina da amministrare sia collegata in quel momento a Internet e che l'amministratore ne conosca o venga a sapere in qualche modo (ad esempio con winipcfg) l'indirizzo IP corrente (che spesso cambia da sessione a sessione).

 

Cap. 3     Il Client .

Il Client del Trojan Pok.

Lanciare il programma client (Pok_Client.exe) sulla macchina dell'amministratore e impostare un workspace con le medesime configurazione del Server precedentemente impostato. Create una nuova definizione di connessione cliccando sul pulsante che reca l'iconcina di un computer, nella zona in basso a sinistra. Compare la schermata mostrata qui sotto.

 

 

fig.11  Aspetto del Software Client di Pok con nessuna opzione attivata.

 

·         Nella casella Name of this server immettete un nome qualsiasi che vi ricordi a quale computer è destinata questa connessione (ad esempio Computer di Anna).

 fig .12 Configurazione del Client.

·         Nella casella Indirizzi Server immettete l'indirizzo IP della macchina server (nell'esempio, visto che si tratta di una rete locale, l'indirizzo è fisso e in questo caso specifico è 192.168.0.1). Probabilmente si dovrà immettere anche il numero della porta definito poco fa (in questo esempio, quindi, la casella contiene 192.168.0.1:18006).  La sottostante fig. 13 mostra l’iserimento di un primo Server sul Workspace

A questo punto cliccate su OK e poi su Click to Connect. Se tutto funziona, dovreste ottenere la risposta del programma server nella zona inferiore della finestra di dialogo.

Nota per gli utenti di Zone Alarm: al primo tentativo di connessione, se c'è Zone Alarm sulla macchina client, il tentativo verrà rilevato e intercettato da Zone Alarm. Zone Alarm identificherà correttamente il programma client come Pok_Client. Questo allarme non costituisce un segnale di pericolo: anzi, indica che Zone Alarm sta facendo il suo dovere.
Se invece Zone Alarm è presente sulla macchina server, rileverà il tentativo di connessione da parte del programma server di Pok..

 

Nel caso dell'amministrazione remota via ethernet, se la macchina server è impostata per adoperare le funzioni di risparmio energetico e queste funzioni disattivano o mettono in standby la scheda di rete (esempio tipico: laptop con scheda di rete PCMCIA), la connessione non si attiva. Per attivarla occorre "svegliare" la macchina server, premendo un tasto o muovendo il mouse o simili, questo implica che solo se il PC che ha subito l’attacco con queste opzionio attive è in uso, ovvero ha il proprietario alla tastiera, sarà possibile prenderne il controllo.

 

 

Attenzione: Il programma esposto in questa Tesi non è l’unico esistente in grado di svolgere queste azioni, quindi si consiglia vivamente a tutti i possessori di un PC collegato ad un modem di disabilitare l’opzione Wake-Up on modem ring, presente tra i vari settagli del BIOS, infatti è possibile accendere un PC ed allacciarlo a internet con l’ausilio di alcuni Plug_in (file .DLL opzionali ).

E’ facile immaginare quali possano essere i danni che un amministratore poco coscienzioso o un Hacker potrebbero  fare se gli lasciassimo a disposizione la macchina per tutta la settimana in cui ci troviamo in vacanza al mare.

 

 

 

Primi test del sistema.

Installato il Server possiamo cimentarci con l'amministrazione remota della macchina remota. Giusto per fare qualcosa di sicuramente innocuo e verificare che tutto funzioni, provate a mandare un messaggio allo schermo della macchina da amministrare:

·         Scegliete la cartella GUI e la voce System Message Box.

·         Nella casella Title, immettete il titolo che volete dare alla finestra del messaggio. Nella casella Text, immettete il testo del messaggio.

·         Cliccate su Send Command. Il messaggio compare sullo schermo della macchina da amministrare. Il programma client conferma la visualizzazione del messaggio sulla macchina server segnalando Dialog box displayed.

Per terminare la connessione, cliccate su Disconnect. Chiudete il client: vi viene chiesto se volete salvare il workspace (ambiente di lavoro). Salvatelo con un nome che ricordi la macchina server a cui è abbinato.

 

Come si disinstalla il programma server Pok_Server.exe

·         Eliminate il file di installazione del programma server (nell'esempio, Sony.exe), altrimenti potrebbe essere riattivato (volontariamente o meno) eseguendolo con un semplice doppio clic. L'amministratore può anche cancellare questo file da remoto.

·         Eliminate il file umgr32.exe che si trova nella cartella system di Windows (per Windows 95/98) o nella cartella system32 (per Windows NT), come descritto qui sotto.

Attenzione: durante la configurazione del programma server è possibile dirgli di installarsi con un nome diverso da umgr32.exe (che è il default). In tal caso, ovviamente, andrà cercato e cancellato un file con il nome che gli avete detto di usare.

Se avete attivato l'opzione Stealth > Run at startup, eliminare il file umgr32.exe (eventualmente rinominato) non è facile, perché Windows se lo riserva come file di sistema e non ne consente la cancellazione diretta (o se la consente, va in crash parziale o completo subito dopo). Posso proporre due soluzioni:

·         l'utente della macchina da amministrare può uscire a DOS e cancellarlo da DOS. Ovviamente, se l'utente non è capace di fare queste cose, questa soluzione è impraticabile: certo, si può sempre andare fisicamente alla macchina da amministrare e provvedere alla cancellazione del file, ma  verrebbe  meno l'ideale di amministrazione remota.

·         L'amministratore può usare il programma client per ordinare al programma server di sganciare da Windows il proprio file, così Windows non lo considera più come file riservato e l'utente della macchina da amministrare può cancellarlo usando le normali procedure di Windows. Ovviamente, se l'amministratore vuole cancellare da remoto il file di installazione (Sony.exe nell'esempio), lo deve fare prima di eliminare il programma server dalla macchina server. Questa è di gran lunga l'opzione più efficace.

La seconda soluzione si esegue in questo modo:

·         L'amministratore si collega alla macchina server usando il programma client di Pok.

·         Una volta stabilita la connessione, l'amministratore seleziona, nel programma client, la cartella Server Control e l'opzione Shutdown Server, digita DELETE nella casella Type 'DELETE' to ERADICATE, e infine clicca su Send command.

·         Questo comando toglie dal Registro della macchina da amministrare l'istruzione di avviare automaticamente Back Orifice a ogni avvio di Windows e sgancia da Windows il file del programma server umgr32.exe (eventualmente rinominato, come da nota qui sopra).

·         A questo punto basta dire all'utente della macchina da amministrare di cancellare il file del programma server con le procedure normali.

A questo punto state impartite le nozioni necessarie per rendere l’utente in  grado di configurare, installare e disinstallare Pok. Adesso vediamo come usarlo per fare molto più che visualizzare una finestra di messaggio sullo schermo della macchina da amministrare.

 

Cap.4     Espandere Pok con i plug-in .

 

Espandere Pok con i plug-in

Un plug-in di Pok è un programma supplementare che amplia le funzioni della versione di base del sistema di telecontrollo. In questa sezione vedremo come prelevare, installare, configurare e usare un plug-in.

Lo scopo accademico della presente Tesi esula dall’implementazione delle classi relative ai plug in, (cosa che tra l’altro risulterebbe davvero molto complessa) percui si è mantenuta la compatibilità con un gruppo di “opzionali” nati per un noto “Trojan “  sviluppato a cura del culto della mucca morta.

Procurasi i plug in non è poi così difficile e si lascia volontariamente un pò di mistero in merito, anche con il duplice scopo di dissuadere chi venisse in qualche maniera in possesso del programma Pok ad usarlo. Ribadisco che è e deve rimanere una trattazione accademica, non sono mai state rilasciate copie degli eseguibili e dei sorgenti, che la presente è depositata con atto notarile in territorio Svizzero.

Si sottolinea in modo particolare che l’eventuale venuta in possesso da parte di chicchessia del programma si deve risolvere con l’immediata cancellazione.

Chiunque Abusi delle potenzialità di questo programma lo fa a suo rischio e pericolo e in piena coscienza di tutti questi avvertimenti impartitogli.

Analoghi avvisi sono stati inseriti tra le schermate del Software, quindi chi lo usasse ne viene portato per forza di cose a conoscenza.

 

Prendiamo come esempio BO_Peep, un plug-in che consente di vedere sullo schermo della macchina dell'amministratore quello che compare sullo schermo della macchina da amministrare.

Il plug-in deve essere innanzitutto configurato usando Pok_config nella sezione dedicata a questo scopo.

 

 

Configurare un plug-in per il programma server

·         Per prima cosa occorre mettere il plug-in nella directory in cui è installato il programma server di Pok creato precedentemente.

·         Lanciate il programma di configurazione del server (Pok_config.exe) e uscite dal Wizard.

·         Cliccare su Open Server e selezionate il programma server che è stato appena creato (Sony.exe). E' questo il file che verrà modificato, integrandovi bo_peep.dll.

·         Cliccare su Insert. Dalla finestra di dialogo che compare,e selezionare il file bo_peep.dll.

·         Spesso a questo punto ci sono dei parametri da configurare, ma in questo semplice esempio l'amministratore accetta i valori di default e quindi non è necessaria alcuna configurazione. Il parametro più importante di cui prendere nota è il numero della porta che verrà utilizzata dal plug-in.

·         Cliccate su Save server e poi su Close server. Questo aggiorna il file del programma server (nel nostro esempio Sony.exe).

Installare un plug-in sulla macchina da amministrare

Il procedimento è il solito: basta copiare il programma server (che ora include il plug-in, in un unico file) alla macchina da amministrare e poi eseguirlo o farlo eseguire.

Conviene rimuovere o far rimuovere dalla macchina da amministrare qualsiasi copia precedente di Pok_Server prima di installare quella aggiornata.

 

Configurare il plug-in sulla macchina dell'amministratore

Può sembrare strano, ma prima di poter utilizzare un plug-in occorre installarlo ed eventualmente configurarlo anche sulla macchina dell'amministratore.

·         Lanciare il programma di configurazione del programma client (Pok_config.exe) sulla macchina client (cioè quella dell'amministratore).

·         Se il plug-in in questione non è già stato installato, cliccare sul menu Plugins, scegliere Configure e poi Insert e selezionare il file del plug-in (in questo caso bo_peep.dll) che si desidera installare sulla macchina da amministrare. Infine cliccare su Done. E' sufficiente eseguire questo passo una volta sola per ciascun plug-in, anche se usate quel plug-in in più di un programma server.

·         La configurazione vera e propria è necessaria soltanto se sono stati cambiati i valori di default in fase di  configurazione del  plug-in per il programma server. Se non sono state apportate modifiche allora il sistema è pronto per procedere; altrimenti vanno modificati (devono essere uguali nel programma server e nel programma client).

Usare il plug-in

Una volta copiato e attivato il server di Pok sulla macchina da amministrare, ci si collea come come già descritto. Una volta ottenuto il collegamento, l'elenco dei comandi mostrerà una cartella nuova, di colore azzurro (in questo caso di nome BO_peep): qui si specificano i comandi che controllano il plug-in.

·         Nella finestra di dialogo del client Pok, aprite la cartella dei comandi del plug-in (BO_peep) e selezionate il comando di attivazione (in questo caso Start Vidstream) e poi cliccate su Send Command.

·         Nel caso specifico di Bo_peep, immettete alcuni parametri: nella casella FPS digitate il numero di fotogrammi al secondo (diciamo 8, ma non esagerate con numeri troppo alti); nella casella Xres, Yres... digitate 160,120 (sono le dimensioni della finestra che visualizzerà tra poco il contenuto dello schermo della macchina da amministrare); oppure lasciate tutto vuoto e accettate i valori di default.

·         Cliccare sulla voce di menu Plugins e scegliere il nome del plug-in (BO_peep) dal menu e, da questa scelta, l'opzione che è stat attivata nei passi precedenti (in questo caso VidStream Client). Nel caso di Bo_peep compare una piccola finestra azzurra. Cliccate su Connect.

·         Accettare i parametri proposti, tranne il primo (Server Address, che va modificato immettendo l'indirizzo IP della macchina da amministrare, seguito da simbolo di due punti e dal numero della porta usata dal plug-in, come indicato durante la configurazione (nel nostro esempio il primo parametro diventa 192.168.0.1: 18006). Cliccate su OK.

·         Il plug-in è in funzione. Nel caso di Bo_peep, dopo l'attivazione del VidStream sul vostro schermo compare una porzione, in scala 1:1, dello schermo della macchina da amministrare. La porzione segue i movimenti del mouse della macchina da amministrare. Ogni movimento che avviene sullo schermo di quella macchina compare anche sul vostro schermo. Questo vi consente, ad esempio, di aiutare l'utente da amministrare: se gli compare ad esempio un messaggio o una schermata a cui non sa rispondere, potete chiedergli di far scorrere il suo mouse sulla parte di schermo che contiene il problema.

Molti plug-in offrono più di una funzione: ad esempio, Bo_peep consente non soltanto di vedere la schermata dell'utente da amministrare, ma anche (se necessario) di prendere il controllo del suo mouse e della sua tastiera.

·         Nella finestra che contiene i comandi del programma client, l'amministratore attiva l'opzione di Bo_peep denominata Hijack cliccando su Start Hijack e poi su Send command.

·         Dal menu Plug-ins, l'amministratore sceglie di nuovo Bo_peep, ma invece di selezionare VidStream Client seleziona Hijack Client: compare la finestra Console Hijack Client, nella quale clicca su Connect.

·         Nella finestra di dialogo che compare, l'amministratore immette (nella casella Server Address) l'indirizzo IP della macchina da amministrare, seguito da simbolo di due punti e dal numero della porta usata dal plug-in per questa funzione, come indicato durante la configurazione (nel nostro esempio, quindi, 192.168.0.1: 18006).

·         Fatto questo, l'amministratore clicca sul pulsante con l'immagine del mouse e/o su quello con l'immagine della tastiera per prendere il controllo dei medesimi sulla macchina da amministrare. L'utente da amministrare perde il controllo del mouse e della tastiera.

·         L'amministratore digita Ctrl-Alt-Z: il suo cursore diventa un pallino rosso, e i suoi spostamenti comandano il cursore del mouse della macchina remota da amministrare. Analogamente, le digitazioni della tastiera dell'amministratore vengono ricevute ed eseguite sulla macchina da amministrare.

Cap. 5    Scoprire l'indirizzo IP della macchina da amministrare

Uno dei problemi dell'amministrazione remota via Internet è che l'amministratore ha bisogno di conoscere l'indirizzo IP corrente della macchina da amministrare. Solitamente questo indirizzo non è statico, ma varia ogni volta che la macchina da amministrare si collega a Internet.

Se l'utente da amministrare è ragionevolmente competente nell'uso di Windows, esiste un modo semplicissimo di determinare l'indirizzo IP: L'amministratore chiede all'utente di eseguire la seguente procedura:

·         L'utente da amministrare si collega a Internet. Deve restare collegato durante questa procedura e non deve scollegarsi da Internet finché glielo dice l'amministratore.

·         Dal menu Start, l'utente da amministrare sceglie Esegui e digita winipcfg. Ottiene una finestra di questo tipo:

·         In questa finestra, l'utente seleziona dal menu a tendina la voce PPP adapter o simili (l'importante è che parli di PPP) e poi guarda il numero indicato alla voce IP Address o simile (comunque è il secondo numero dall'alto). Nella figuraè riportato l’indirizzo statico della rete locale 192.168.0.207.

·         L'utente da amministrare comunica all'amministratore il numero relativo alla coesione internet PPP, che è l'indirizzo IP. La comunicazione va fatta senza interrompere la connessione a Internet. L'utente può ad esempio mandare un e-mail all'amministratore oppure telefonargli su un'altra linea o sul cellulare.

·         A questo punto l'amministratore sa tutto quello che gli serve per accedere alla macchina da amministrare.

L'alternativa: notifica automatica via e-mail

Purtroppo non tutti gli utenti Windows sono abbastanza competenti da eseguire la procedura descritta sopra (altrimenti non avrebbero bisogno di amministrazione remota), per cui capita spesso che l'amministratore abbia bisogno di scoprire l'indirizzo IP senza dover disturbare l'utente.

Per questo si può ricorrere a un altro plug-in, di nome Butt Trumpet, facilmente reperibile in Rete. L'installazione segue la falsariga di quella del plug-in precedente. Il risultato è che ogni volta che la macchina da amministrare si collega a Internet, Pok_Server spedisce all'amministratore un e-mail contenente l'indirizzo IP corrente della macchina da amministrare. Semplice, pratico, facile.

 

 

Cap.6  Protocollo e Crittografia  

Il protocollo

Il cambio di dati tra il CLIENT e SERVER POK è fatto utilizzando pacchetti UDP (utent datagram protocol) crittografati. Il formato di questi è semplice, così come è lo schema crittografico utilizzato. Il server si collega normalmente alla porta 31337 UDP, ma può essere configurato ad uso un altra porta. Tutti i pacchetti POK dal server al client o vice-versa hanno lo stesso formato di base. Notate che anche se nessuna password è realizzata sul server o sul client, i pacchetti POK sono comunque sempre crittografati.

Formato di pacchetto

I pacchetti POK sono composti di una testata dei 17 byte che contiene le caratteristiche del pacchetto, oltre a dati di carico utile (almeno 1 byte.) I pacchetti finiscono con un  byte CRC.

Campi di pacchetti:

Strumento mnemonico

Dimensione in byte

Magia

8

LEN

4

ID

4

T

1

Dati

Variabile

CRC

1

Campi di testata

MAGIC - una stringa di otto byte che identifica il pacchetto POK. La sequenza di caratteri è fissa e deve essere la stringa *!*QWTY?"(Stella, colpo, stella ", Q" ", W" ", T" ", Y, "domanda.)

Intero di 32 bit LEN - A che contiene la lunghezza dell'intero pacchetto, compreso la testata. Il valore di questo campo non può essere meno di 19 (la lunghezza di testata oltre a, almeno, 1 byte di dati  e 1 byte CRC.)

Intero di 32 bit ID - A che contiene l'identificazione del pacchetto UDP. Questo campo è utilizzato per tenere traccia del numero di sequenza di frammento di pacchetti dall’algoritmo di trasmissione frammentati?. È utilizzato anche dal client POK per fare coincidere un pacchetto ricevuto con i pacchetti precedentemente inviati.

Gli " interi di 32 bit "utilizzati nella testata di pacchetti POK non sono trasmessi in ordine di rete, ma con il suo byte meno significativo inviato per primo. Per esempio, " l'intero0x11bb55eeÈ trasmesso in  questo ordine: 0xee, 0x55, 0xbbE0x11.

T - questo campo contiene il tipo di operazione che il pacchetto porta, i 2 pezzi più significativi sono utilizzati per segnalare alcune condizioni sul pacchetto, come la frammentazione di un grande pacchetto. I restanti 6 bit sono utilizzati per specificare l'operazione POK effettiva.

Dati

Il campo dati di un pacchetto POK segue giustamente la testata. È composto di una sequenza semplice di caratteri, finito da un carattere con codice ASCII0 (zero) -- NUL. Questo carattere di terminatore è obbligatorio.Il contenuto del campo di dati dovrebbe essere interpretato diversamente se il pacchetto va dal server al client, o se entra in modo contrario. In pacchetti che vanno dal client al server, consentono l’invio di fino a due sequenze di stringhe che  possono essere inviate nel campo di dati, poiché essi sono separati da un carattere NUL. In pacchetti che vanno dal server dal client, c'è solo una stringa con la risposta al  comando

 

CRT

 Dopo il campo dati, c'è un campo di 1 byte contenendo il CRC del pacchetto. IL client POK ignora il valore di questo byte.

 

Crittografia

Tutti i pacchetti POK sono crittografati. L'intero pacchetto POK (includendo la testata) è crittografato. Lo schema crittografico utilizzato è semplice, e dipende da una chiave segreta (la password) che deve essere conosciuto dalle due parti. La password è utilizzata per solo crittografare pacchetti; la password non percorre mai la rete, non può quindi essere agganciata durante il transito da appositi programmi (sniffer).

La crittografia è fatta applicando (un'or esclusiva ) operazione XOR tra ogni byte del pacchetto e il valore consecutivo ritornati da un generatore di numero casuale. Questo generatore è inizializzato con un valore che dipende dalla password segreta utilizzata nella comunicazione. In questo modo, avendo la stessa password, sia il generatore di numero casuale (il server e il cliente ) sarà inizializzato con lo stesso seme, percui essi restituiranno la stessa sequenza di " "numeri casuali "che saranno utilizzati per crittografare/ decrittografare il pacchetto.

Questo schema crittografico non è forte, del resto la crittografia avviane per ogni singolo pacchetto che  contengono sempre una sequenza fissa di caratteri (MAGIC) nella testata. Da ispezione di un singolo pacchetto crittografato può essere possibile ottenere la sequenza iniziale di numeri casuali generata, quindi è possibile utilizzare un attacco di forza brutale per scoprire il seme di generatore di numero casuale. Questo è molto fattibile perché la gamma di possibili valori è piuttosto piccola. I metodi utilizzati per decrittografare e crittografare un pacchetto POK senza sapere la password che è utilizzata è rintracciabile nella bibliografia studiando gli algoritmi di estrazione dei mulinelli Random.

Il generatore di numero casuale

Il protocollo POK utilizza la seguente funzione di generatore di numero casuale:

POKRAND(x) = (x * 214013) + 2531011

Dove A * B "Indica la moltiplicazione di A per B,  e +La solita operazione di somma”.

Il valore del parametro iniziale del (seme) è derivato dalla password di comunicazione (vedete sotto.) Il valore successivo è sempre il risultato del valore restituito dall'ultima corsa. Per esempio, una sequenza di " "numeri casuali X1, X2, ..., Xn Può essere ottenuto nel modo seguente:

X 1 = POKRAND (IV) X 2 = POKRAND (X 1) X 3 = POKRAND (X 2 ...) X n = POKRAND (X n - 1)

Dove IV È il seme e Xn È il numero casuale  ennesimo.

Il seme

Il seme da utilizzare sul generatore di numero casuale POK è generato utilizzando la password di comunicazione. Se nessuna password viene utilizzata, il valore di 31337 speciale è impiegato come il seme. Altrimenti, il seguente algoritmo dà il seme da una password S:

 

X = 0 Y = length (number of characters) of S Z = 0 WHILE X < Y
    Z = Z + S[X] X = X + 1 END X = 0 WHILE X < Y IF X is odd 
    Z = Z - (S[X] * (Y - X + 1)) ELSE Z = Z + (S[X] * (Y -
    X + 1)) END Z = Z % 0x7fffffff X = X + 1 END Z = (Z * Y) %
0x7fffffff IV = Z
 

DoveS[n]"È il carattere  ennesimo della password A % B " Il resto della divisione di A per B, e IV" Il seme che stiamo cercando.

Nota: Il generatore di numero casuale è  re+ inizializzato con lo un nuovo seme ogni volta che un pacchetto è inviato.

 

 

Crittografando/ decrittografando

Il seguente algoritmo è una dimostrazione di come può essere crittografato o decrittografato un pacchetto POK:

L = lunghezza di un pacchetto POK X =0 Z = IV WHILE X < L Z = POKRAND (Z) P [X] = P [X] ^ ((Z > > 16) & 0xff) X = X + 1 END

DoveP[n]"Indica il byte  ennesimo del pacchetto A ^ B"L'operazione XOR bit a bit tra A e BA >> B"Il cambiamento di 32 bit di A per B pezzi nella destra,  A & B"L'operazione AND bit a bit tra A e B.

 

Trasferimento file TCP

Il trasferimento di archivi che utilizzano TCP (operazioni TYPE_TCPFILESEND e TYPE_TCPFILERECIVED) è fatto con l'apertura del server tramite la porta  specificata nel parametro del comando.

Quando il CLIENT invia un pacchetto TYPE_TCPFILESEND, il server apre l'archivio specificato e aspetta di sentire un collegamento TCP sulla porta TCP specificata. Quindi il CLIENT si collega a quella porta e inizia inviando l'archivio.

Quando il CLIENT desidera ricevere un archivio, invia un pacchetto TYPE_TCPFILERECEIVE specificando il nome archivio chiesto e la  porta TCP. Il server quindi aprirà la porta specificata e comincerà a trasferire l'archivio non appena qualcuno (probabilmente il CLIENT) si gli collega.

 

Determinazione se POK è stato installato sulla vostra macchina:
Il server POK esegue numerose operazioni poiché si installa su un ospite di destinazione
:

Azione raccomandata:
POK può essere rimosso cancellando il server e eliminando la sua entrata di registrazione. Se possibile, dovreste sostenere tutti i dati di utente, formattare il vostro disco rigido, e reinstallare tutti i sistemi operativi e il software nella macchina infettata. Determinazione della password e della configurazione di un installazione POK:
1. Utilizzando un editor di testi come il blocchetto per appunti, esaminate il server  exe .
2. Se l'ultima riga dell'archivio è '8 8$8 (8,8084888 < 8@8D8H8L8P8T8X88'8d8h8l8,' quindi il server sta utilizzando la configurazione di default. Altrimenti, la configurazione vuole sono le 'ultime numerose righe di questo archivio, in questo ordine:

 

Cap.7  Il protocollo TCP/IP

"la suite di protocolli TCP/IP" definisce le regole utilizzate per la trasmissione su Internet.

Il nome completo è TCP/IP Internet Protocol Suite, ed è un insieme di protocolli di trasmissione di cui i due principali sono appunto il TCP (Transmission Control Protocol) e l'IP (Internet Protocol). Ma che cosa è esattamente un protocollo? Essenzialmente è una serie di regole per comporre dei messaggi e per far sì che essi possano essere scambiati tra due macchine. Non stiamo parlando solo di computer. Anche una centrale telefonica meccanica può ricadere in questa definizione. Un protocollo può contenere regole estremamente dettagliate, come quelle che identificano il significato di ogni singolo bit nella costruzione di un messaggio, oppure fornire uno scenario di alto livello, come per esempio definire come avviene il trasferimento di un file da un computer a un altro.

Una generica architettura di trasmissione è formata da una torre a più piani, dove ogni piano rappresenta una precisa responsabilità nella trasmissione dei messaggi. Alla base della torre sta la porta di accesso alla rete fisica, che potremmo pensare come una rete di strade. Ogni piano prende il messaggio che arriva dal piano superiore, lo mette in una busta con alcune informazioni aggiuntive, e lo passa come messaggio al piano inferiore.

Le regole di comunicazione tra i vari piani sono dette interfacce. Il messaggio risultante, formato da tante buste una dentro l'altra, viene immesso nella rete dalla porta che si trova alla base della torre. Una volta arrivato al piano terreno infatti, esso viene trasportato alla torre di destinazione e da qui risale un piano dopo l'altro fino all'ultimo piano, detto anche livello applicativo. Ogni piano della torre di destinazione apre solo la busta che gli compete e usa le informazioni aggiuntive per recapitare la busta successiva al piano superiore. Le informazioni aggiuntive rappresentano il protocollo di comunicazione. Ogni piano comunica quindi solo con il piano corrispondente.

La base di ogni protocollo è il concetto di standardizzazione. Più vasta è l'accettazione dello standard, più forte e diffuso è il protocollo. Gli standard internazionali sono in genere i più importanti, ma non sempre. Un esempio è proprio il TCP/IP, nato per volontà dell'agenzia americana DARPA (Defense Advanced Research Projects Agency) e poi diventato di fatto il maggior sistema di protocolli per l'interconnessione di reti a livello mondiale.

Internet è fatta a strati Internet è basato su tre livelli concettuali: il livello applicativo (Application Services), quello del trasporto (Reliable Stream Transport Service) e quello della spedizione dei pacchetti (Connectionless Packet Delivery Service). Per capire il TCP/IP, è necessario a questo punto capire bene che cosa è Internet. Tanto per cominciare Internet non è una rete di comunicazione. Una rete di comunicazione è in genere legata alle necessità specifiche di chi l'ha disegnata e dell'hardware utilizzato per implementarla. Costruire una rete ideale che vada bene per qualsiasi esigenza, o pensare di poter limitare a un solo tipo di hardware l'implementazione di una qualunque rete non solo non è fattibile, ma neanche auspicabile, date le limitazioni delle tecnologie attuali. A volte è necessario far correre i dati molto velocemente in un ambito molto ristretto, come per esempio all'interno di un edificio.

Altre volte si ha l'esigenza di trasmettere dati a migliaia di chilometri di distanza in modo molto affidabile, anche se questo può significare un rallentamento nella velocità di trasmissione. Se si cercasse di utilizzare lo stesso hardware in entrambi i casi, i costi sarebbero assolutamente inaccettabili.

La soluzione è l'interconnessione delle reti, o internetworking. Grazie a ponti di collegamento (detti gateway) e la definizione di opportuni protocolli, si possono collegare fra di loro reti anche molto diverse, fornendone agli utenti una visione comune. Questa è la forza di Internet rispetto alle varie reti proprietarie, e di conseguenza del TCP/IP sui vari protocolli proprietari. Il TCP/IP è un insieme di regole pubbliche, aperte a tutti, o come si dice nell'ambiente, un sistema aperto (open system), che permette l'interconnessione di reti anche molto differenti, indipendentemente dalla tecnologia usata da ogni rete. I suoi principali vantaggi sono appunto l'indipendenza dalle tecnologie delle singole reti interconnesse, la possibilità di far comunicare fra di loro ogni computer connesso al sistema, la possibilità di trasmettere conferme di ricezione (acknowledgement) direttamente dal destinatario al mittente, e soprattutto una notevole quantità di protocolli applicativi per qualunque possibile bisogno, come vedremo più avanti. Il TCP/IP definisce quindi una unità di trasmissione dati chiamata datagram, e le regole da seguire per trasmettere un datagram in una particolare rete.

Il principio che sta alla base dell'interconnessione è quello di schermare le applicazioni dalle caratteristiche fisiche delle reti in modo semplice e flessibile. Questo avviene attraverso un livello intermedio che si occupa di spedire e ricevere piccoli pacchetti di dati fra due punti qualsiasi del sistema di reti. Questo meccanismo si chiama packet-switching. Esso consiste nella divisione di ogni messaggio in un certo numero di pacchetti di dati. Ogni pacchetto è formato da poche centinaia di byte, e contiene una intestazione che fornisce informazioni sul destinatario e su come raggiungerlo. Questo meccanismo ha il vantaggio di ottimizzare l'utilizzo della rete, parallelizzando la trasmissione di più messaggi contemporaneamente. Lo svantaggio è che ogni nuovo sistema che si aggancia alla rete per trasferire dati riduce la disponibilità della rete per tutti gli altri sistemi già connessi. Una rete infatti ha una certa capacità ben definita, che dipende sostanzialmente dalla tecnologia hardware e software che utilizza.

Tale capacità viene misurata in bit per second (bps). Questa grandezza non rappresenta la velocità dei dati in rete, come si potrebbe pensare in prima istanza, bensì dà una misura del numero massimo di bit che possono essere trasmessi nella rete in un secondo. La velocità reale di un singolo messaggio dipende da tanti fattori, come il numero di sistemi che stanno utilizzando la rete, la qualità delle connessioni e di conseguenza il numero di tentativi necessari per trasferire correttamente i dati, le modalità di trasmissione e i dati aggiuntivi necessari al trasferimento degli stessi.

Ci sono altri modi per trasferire dati in una rete: per esempio, quando fate una telefonata, la rete stabilisce un collegamento diretto fra il vostro telefono e quello della persona chiamata. A questo punto il telefono incomincia a campionare il microfono della vostra cornetta in modo continuo, trasferendo il segnare al ricevitore all'altro capo. Il tutto a 64.000 bit per secondo, che è la velocità di campionamento necessaria a digitalizzare la voce. Questo avviene comunque, indipendentemente dal fatto che stiate parlando o meno. Anche se state in silenzio la linea è saturata al massimo della sua capacità. Questo meccanismo è detto circuit-switching. Al contrario del meccanismo usato dal TCP/IP, quello cioè a pacchetti, la linea è completamente assegnata alla comunicazione in atto, per cui il fatto che altri stiano telefonando non riduce la capacità della connessione. D'altra parte la linea è utilizzata completamente indipendentemente dal fatto che ci siano o meno dati da trasferire. Di qui gli elevati costi di tale meccanismo. La telefonata, infatti, la pagate lo stesso sia che parliate molto velocemente, sia che stiate completamente in silenzio. Questo meccanismo è troppo costoso per una rete informatica, specialmente se si tiene conto che la disponibilità di tecnologie hardware sempre più raffinate e veloci per il trasferimento dei dati bilanciano in buona parte quello che è uno dei punti deboli del sistema a pacchetti, e cioè l'impossibilità di garantire a ogni utente e in ogni momento una certa capacità di trasferimento ben definita.

 

L’indirizzamento.

Torniamo al sistema a pacchetti. Per trasferire dati da un sistema a un altro ogni sistema ha un nome unico ben definito. Non esistono cioè due sistemi con lo stesso nome, anche se in reti diverse, indipendentemente da quale è il nome locale di un sistema nella sua rete di appartenenza. All'interno di ciascuna rete, i vari computer usano la tecnologia hardware e software specifica di quella rete. Tuttavia, grazie a questo strato intermedio di software, le varie applicazioni hanno una visione unica e globale del sistema interconnesso di reti, detto appunto internet. Notate la "i" minuscola. Il concetto di internet è infatti quello appena descritto. Viceversa Internet con la "I" maiuscola, identifica quel sistema di reti, basato sull'architettura internet, che viene detto anche Connected Internet.

La connessione tra due reti avviene attraverso macchine opportune che sono collegate fisicamente a entrambe le reti, e hanno la responsabilità di far passare i vari pacchetti da una rete all'altra e viceversa. Tali macchine sono dette internet gateway, o anche IP router. Sono loro il vero elemento portante di una internet. Ogni router non solo deve sapere che determinati pacchetti vanno passati da una rete a un'altra, ma deve passare dall'altra parte anche pacchetti destinati a ulteriori reti connesse attraverso altri router. Essi però ragionano solo in termini di reti, non di destinazione finale. A un router non interessa chi è effettivamente il destinatario di un pacchetto, ma solo a quale rete appartiene. Questo semplifica molto l'implementazione di un router. Alla base del meccanismo dei router c'è l'indirizzo IP, o IP address.

Come nascono gli identificativi Internet.

Ogni cosa che conosciamo ha un nome. Cane, casa, auto, e via dicendo. Se ci interessa specificare meglio ciò di cui stiamo parlando, possiamo assegnare un nome anche a un sottogruppo di cose. Così abbiamo che i cani bassotti sono alquanto diversi dai San Bernardo, una catapecchia non è certo una villa, e una Ferrari costa un po' più di una Cinquecento. Se poi dobbiamo identificare una cosa in modo chiaro e univoco, è necessario assegnarle un nome che solo quella cosa ha. Già un nome come Mario Rossi non va bene, perché non è unico, e comunque, anche se scegliessimo oggi un nome veramente strano e originale, non avremmo la garanzia in futuro di non ritrovarci con un caso di omonimia. Ecco allora le targhe per le automobili, i codici fiscali per le persone, i numeri di telefono, e via dicendo. Ognuno di questi nomi ha tre caratteristiche. La prima è che esiste un organo competente centrale che li assegna, proprio per garantirne l'univocità. La seconda, è che hanno una struttura a sottogruppi. Esistono cioè degli elementi che garantiscono l'univocità a un certo livello, all'interno del quale esiste una certa libertà di scelta, e così via, livello dopo livello. Per esempio, il codice fiscale viene costruito in modo che un uomo e una donna non possano mai avere lo stesso codice, anche se fossero nati lo stesso giorno, nella stessa città e si chiamassero nello stesso modo. Similmente, i numeri di telefono di due città diverse si distinguono per il prefisso e se queste si trovano anche in stati diversi, per il prefisso internazionale.

Affinché internet possa rappresentare un sistema universale di comunicazione, permetta cioè di far comunicare qualunque macchina connessa a una delle sue reti con una qualsivoglia altra macchina connessa alla stessa o a un'altra rete, è necessario fornire ogni macchina di un nome unico a livello globale. Internet fornisce ogni sistema di un nome, che identifica il sistema stesso, di un indirizzo, che mi dice dove si trova il sistema, e di un cammino, che mi dice come raggiungere il sistema. Ogni macchina connessa a una rete è detta host, nella terminologia internet.

Gli indirizzi IP

L'indirizzo, o IP address, è un campo composto da 32 bit. I primi bit permettono di distinguere 5 forme standard identificate da una lettera del alfabeto, e dette classi. Le prime tre classi dell'IP address contengono sia l'indirizzo di una rete (netid), sia quello di una macchina nella stessa (hostid). In realtà l'indirizzo non identifica necessariamente una macchina, ma una connessione alla rete. Per esempio, un router ha almeno due indirizzi, avendo connessioni ad almeno due reti. Questo in quanto un router appartiene a entrambe le reti, e quindi sono necessari due indirizzi dato che un IP address ha posto per un solo indirizzo di rete. Se l'indirizzo dell'host è 0, allora l'IP address si riferisce alla rete stessa. Se viceversa tutti i bit riservati all'indirizzo dell'host sono 1, allora l'indirizzo viene utilizzato per identificare tutti gli host della rete (broadcasting). Uno speciale indirizzo formato da 32 bit posti a uno è chiamato local network broadcast address e serve solo in casi molto particolari. Il concetto di broadcasting è quello della diffusione a tutto raggio, un po' come fa un'emittente radiofonica. In generale internet interpreta i campi formati da tutti uno come all, cioè "tutti", mentre quelli formati da tutti zero come this, cioè "questo", "qui". Questo per quanto riguarda le classi A, B e C. La classe D è usata per un particolare tipo di distribuzione dei dati detto multicasting. La classe E è riservata a usi futuri. Dato che specificare ogni singolo bit di un indirizzo IP sarebbe alquanto poco pratico e di scarsa leggibilità, la convenzione è quella di leggere ogni ottetto, cioè ogni gruppo di 8 bit, come un intero, e di separare i quattro ottetti con un punto. Oltre a i casi speciali già descritti, l'indirizzo di classe A 127.0.0.0 è riservato per un particolare processo di test che rimanda indietro i dati al mittente senza propagarli nella rete.

Uno dei vantaggi di questo schema è la possibilità da parte dell'organismo centrale che assegna gli indirizzi (Network Information Center) di delegare ai responsabili delle singole reti l'assegnazione di una parte dell'indirizzo all'interno della rete stessa. La cosa avviene un poco come con i numeri di telefono. A livello internazionale ogni stato ha il suo prefisso internazionale. Per esempio, per l'Italia, è 39. All'interno ogni stato divide il paese in aree geografiche a cui assegna un ulteriore codice. Per esempio, Roma è identificata dal 6, Milano dal 2, Firenze da 55, e così via. All'interno poi della provincia o della città possono essere definite ulteriormente sottoaree a cui si assegnano due, tre o quattro cifre. Per esempio 529 oppure 7054. Infine ogni telefono in tali aree avrà il suo numero. Così, se Mr. Smith deve chiamare dagli Stati Uniti il signor Mario Rossi abitante all'EUR, a Roma, comporrà per esempio il numero 011.39.6.529.4467. In questo caso lo 011 serve per uscire dagli USA, un po' come il nostro 00.

Analogamente in internet i numeri di classe C sono assegnati alla piccole reti, quelle cioè con meno di 256 host, quelli di classe B alle reti con al massimo 65536 host, e quelli di classe A alle reti con oltre 16 milioni di host. Ogni rete decide poi come suddividere gli indirizzi che gli sono stati riservati al suo interno come meglio crede. Ovviamente, una internet privata non ha la necessità di seguire queste regole, né a utilizzare indirizzi assegnati dal NIC, ma il non farlo potrebbe impedire in futuro la connessione alla TCP/IP Internet. Dato che l'indirizzo può essere a volte abbastanza ostico da ricordare, è possibili associare a ogni host anche un nome, che può essere utilizzato come mnemonico per un IP address, e la cui risoluzione è responsabilità di particolari macchine chiamate name server. In realtà il name server è un programma software che può girare in qualunque macchina connessa alla rete, e che mantiene l'associazione tra nomi e indirizzi IP, fornendo tali corrispondenze quando richiesto da un altro programma chiamato name resolver. Di fatto, si preferisce far girare il name server su una macchina dedicata, che prende anch'essa, a questo punto, il nome di name server. Potete pensare al name server come a una agenda telefonica elettronica, che contiene una lista parziale di nomi e numeri telefonici. In internet infatti, non esiste un singolo elenco telefonico, ma tanti name server che cooperano per fornire quello che è un vero e proprio elenco distribuito. In realtà il sistema funziona in modo gerarchico, un po' come se una certa agenda contenesse solo i prefissi internazionali e il puntatore alle agende di ogni singolo stato, le quali a loro volta contengono i prefissi regionali e i puntatori agli elenchi regionali, e così via, fino ad arrivare all'agenda che contiene solo le estensioni telefoniche di un singolo edificio.

Il Domain Name System

I nomi Internet sono basati su una serie di regole dette Domain Name System (DNS), che si basa appunto su uno schema gerarchico in cui il nome è suddiviso in varie parti separate fra loro da punti. Per esempio, vnet.ibm.com. Ogni suffisso è a sua volta un dominio. Quindi, nel nostro esempio, ibm.com è un dominio di secondo livello, mentre com è un dominio di terzo livello. I domini ufficiali riconosciuti dal NIC al livello più elevato sono riportati in tabella 1. Una rete può richiedere di essere registrata come categoria, oppure usando il dominio geografico. Per esempio, l'Italia ha come dominio base it. Supponiamo che il governo decida di costruire un insieme di reti cittadine interconesse fra loro e connesse a Internet. Si può pensare di assegnare a ogni provincia un dominio xxxxxx.it. Per esempio, Firenze avrebbe come dominio firenze.it. L'università di Firenze potrebbe registrare la sue rete come unifi.edu, e in tal caso sarebbe direttamente il NIC a dover dare l'autorizzazione per tale nome, essendo il dominio edu sotto responsabilità dell'organismo centrale di controllo, oppure potrebbe decidere di far parte del dominio cittadino, come unifi.firenze.it, e quindi potrebbe richiedere il permesso di registrare tale nome direttamente all'amministratore del dominio di Firenze. A questo punto, se il dipartimento di Fisica di Arcetri vuole registrare un proprio dominio, deve chiederlo solo all'Università stessa, ricevendo così, per esempio, arcetri.usf.fi.it oppure fisica.usf.fi.it. Esiste una piccola complicazione. Ogni oggetto connesso alla rete ha un tipo. Oggetti di tipo diverso possono avere lo stesso nome. Per cui, per poter risolvere un nome e ottenere indietro l'indirizzo IP, è necessario anche specificare il tipo di oggetto: macchina, utente, casella postale, e via dicendo. Dal solo nome non è possibile evincere il tipo di oggetto.

Il DNS definisce anche come associare i nomi agli indirizzi IP, e come ottenere quest'ultimi dal nome. In realtà lo schema è ancora più generale di quanto può sembrare, in quanto permette di estendere la sintassi del nome per usi specifici, sfruttando anche il concetto di tipo. Per esempio, nel caso di una casella postale (tipo MX), il nome sarà del tipo utente@dominio.

Le trasmissioni Internet.

Innanzi tutto una rete internet è un sistema di interconnessione fra reti differenti che utilizza sia sistemi dedicati per la connessione, detti gateway, sia uno strato (layer) di protocolli che mostrano alle applicazioni una visione omogenea di una rete virtuale e che sono basati sulla trasmissione di piccoli pacchetti di dati. Ogni pacchetto porta con sé l'indirizzo del destinatario il quale identifica univocamente sia la rete di destinazione che la connessione alla quale deve essere recapitato il pacchetto. Un sistema connesso a più reti della stessa internet avrà quindi più indirizzi IP. Un opportuno software, spesso installato su macchine dedicate, permette di associare a ogni indirizzo un nome di più facile utilizzo da parte degli utenti del sistema. Il formato di questo nome si basa su un insieme di regole dette DNS. Quella che è universalmente conosciuta come Internet è di fatto la principale rete interconnessa esistente, che si estende praticamente su tutto il pianeta.

Data questa premessa, vediamo di approfondire la trattazione dei protocolli TCP/IP. Innanzi tutto qualunque trasferimento di dati implica la trasmissione di bit da un sistema a un altro. Tali dati devono essere correttamente interpretati dai vari sistemi connessi alla rete. Data l'enorme varietà di hardware e di sistemi operativi questo è tutt'altro che banale. Nei protocolli di trasmissione i bit vengono convenzionalmente raggruppati per multipli di otto, detti ottetti. Una volta questo corrispondeva al bus da 8 bit, cioè un byte, tipico dei computer. Oggi la maggior parte dei computer usa parole di almeno 32 bit. Tuttavia non tutte le macchine memorizzano tali parole nello stesso modo. Esistono vari modi per memorizzare un intero rappresentato da 32 bit. In quello detto Little Endian, la posizione più bassa in memoria contiene il byte di ordine più basso dell'intero. Nei sistemi Big Endian avviene esattamente il contrario, cioè la posizione più bassa in memoria contiene il byte di ordine più elevato. In altri sistemi ancora il raggruppamento viene fatto con parole da 16 bit, in cui la parola meno significativa viene appunto prima. Il risultato è lo stesso del Little Endian ma con i byte invertiti all'interno di ogni singola parola. È evidente che non è pensabile che sia la rete a gestire tutti questi modi diversi di interpretare i dati, anche perché di solito i protocolli di trasmissione non entrano nel merito di come ragionano i singoli sistemi, ma si occupano solamente di trasferire in modo più o meno affidabile i dati a loro affidati. Ne consegue la necessità di definire un formato standard valido per tutti i dati che corrono lungo i collegamenti, lasciando a i vari sistemi il compito di effettuare le opportune conversioni locali. Lo standard internet prevede che gli interi vengano trasmessi a partire dal byte più significativo, secondo lo stile del Big Endian.

Così in un pacchetto, un intero ha il byte più significativo verso la testa del pacchetto e quello meno significativo verso la coda dello stesso.

A questo punto i sistemi sono in grado di scambiarsi i dati in modo non equivoco. Ma come fa a sapere la rete internet che un sistema è collegato, e soprattutto, come avviene l'associazione tra l'IP address e l'indirizzo fisico di rete? Ogni rete fisica infatti ha un suo formato per gli indirizzi fisici assegnati alle connessioni di rete. In generale esistono due modi di assegnare indirizzi fisici alle macchine connesse in rete. In una rete piccola, come può essere una Token Ring, cioè un anello di un paio di centinaia di macchine al massimo, a ogni connessione può essere assegnato un intero basso, per esempio compreso tra 1 e 254. Questo sistema ha il vantaggio di associare l'indirizzo fisico alla connessione piuttosto che alla scheda che permette la stessa. Per cui, se la scheda si rompe, l'utente può cambiarla senza dover tuttavia modificare l'indirizzo fisico di rete, purché imposti sulla nuova scheda lo stesso indirizzo di quella vecchia. Lo svantaggio è che non esiste alcun controllo che impedisca a due utenti sulla stessa rete di impostare lo stesso indirizzo fisico, creando così una collisione. In altri tipi di reti, come per esempio Ethernet, ogni scheda ha già preimpostato da parte del costruttore un indirizzo fisico fisso, per cui non c'è alcun rischio di collisione, ma cambiare la scheda vuol dire dover necessariamente cambiare indirizzo fisico. Inoltre, dato che questo indirizzo è unico non solo fra le schede installate su una certa rete, ma in assoluto fra tutte le schede costruite, esso è generalmente molto lungo. Nel caso di Ethernet è di ben 48 bit.

Associare un IP address a un sistema con indirizzi formati da piccoli numeri e per giunta tali che a parità di connessione l'indirizzo non cambia mai, come nel caso di una rete proNET-10, è molto semplice. Per esempio, per un IP address di classe C, si può usare l'indirizzo fisico come host identifier. Così, se la rete ha IP address del tipo 10.214.32.x, l'host con indirizzo fisico 16 avrà IP address 10.214.32.16. Un altro paio di maniche è gestire indirizzi molto più lunghi dei 32 bit utilizzati per gli indirizzi internet, e per giunta che possono cambiare nel tempo a parità di connessione. Ovviamente si potrebbe tenere da qualche parte una tabella per gli accoppiamenti, e di fatto si fa così, ma non è certo molto pratico pensare che qualcuno la tenga aggiornata a mano. Il problema è stato risolto efficacemente utilizzando un meccanismo di risoluzione dinamica implementato dal protocollo ARP, o Address Resolution Protocol.

 

L’archittetura TCP/IP è basata su tre livelli.

Come detto prima l'architettura internet è basata su tre livelli. L'Application Services è il livello più alto, cioè quello delle applicazioni. I programmi che utilizzate quando usate internet ricadono in questo livello. Il Reliable Stream Transport Service è il livello intermedio. Esso si occupa dell'affidabilità della comunicazione, gestendo gli errori di trasmissione e la perdita di eventuali dati. Esso inoltre fornisce una visione della comunicazione ad alto livello, in cui esiste una connessione tra i due host che si trasmettono grandi volumi di dati. Il livello più basso, chiamato Connectionless Packet Delivery Service è quello che effettua la spedizione vera e propria dei singoli pacchetti, senza garantire l'affidabilità sulla singola trasmissione, nella modalità detta connectionless. Il protocollo su cui si basa il livello più basso della torre internet è appunto l'Internet Protocol, o IP. Tale protocollo si basa su alcuni concetti fondamentali. Innanzi tutto il servizio che fornisce è detto unreliable, cioè inaffidabile, in quanto non dà alcun garanzia che il singolo pacchetto arrivi effettivamente a destinazione. In secondo luogo è detto connectionless, cioè senza connessione diretta, in quanto la trasmissione non avviene direttamente verso il destinatario, ma il messaggio è lanciato nella rete lasciando poi a questa il compito di portarlo a destinazione utilizzando l'indirizzo IP dell'host destinatario. Infine si parla di best-effort delivery, cioè spedizione al meglio delle possibilità, in quanto la rete fa tutto il possibile per portare comunque a destinazione il pacchetto. In pratica l'IP si comporta come un naufrago su un'isola deserta che lancia nella corrente un messaggio in una bottiglia per un tizio che si trova su di un'altra isola dello stesso arcipelago, contando sul fatto che se la bottiglia arriva sull'isola sbagliata qualcuno ributterà a mare il messaggio fintanto che non arriverà a destinazione. Detta così c'è quasi da stupirsi che internet funzioni così bene. Anzi, che funzioni del tutto! In realtà non dimentichiamoci che sopra al livello più basso ce n'è un altro che garantisce appunto l'affidabilità della comunicazione. Torniamo comunque all'IP. Esso è formato da tre regole base: come è fatto il pacchetto da trasmettere, detto IP datagram, come avviene la scelta del cammino che il pacchetto segue per raggiungere il destinatario, come gli host e i gateway devono trattare i pacchetti e in particolare le modalità per l'emissione dei messaggi di errore e quelle per la soppressione dei pacchetti.

Innanzi tutto va ricordato che l'IP è un protocollo unreliable, non dà cioè alcuna garanzia che il singolo pacchetto arrivi effettivamente a destinazione, ed è connectionless, ovverosia il messaggio non viene spedito direttamente al destinatario ma viene immesso nella rete lasciando poi a questa il compito di portarlo a destinazione. Esso inoltre è di tipo best-effort delivery, in quanto la rete fa tutto il possibile per portare comunque a destinazione il pacchetto.

Detto questo, vediamo come avviene la trasmissione vera e propria dei dati. L'unità fisica di trasferimento dei dati in una rete è la frame. Questa è composta di due parti: l'intestazione (header) e l'area dati (data area). L'unità di misura è invece l'ottetto, formato da otto bit, cioè un byte. Ogni rete fisica ha un limite massimo di capacità di trasferimento per un singolo frame, detto Maximum Transfer Unit (MTU). L'MTU è cioè il massimo numero di ottetti di dati che può essere trasferito in un singolo frame. Per esempio, Ethernet ha generalmente una MTU di 1.500 ottetti (1492 secondo lo standard IEEE 802.3). Questo vuol dire che se si devono spedire 2.000 byte di dati via Ethernet, è necessario spezzarli in due blocchi tali che ogni blocco sia minore o uguale a 1.500. A ogni blocco si aggiunge poi l'intestazione del frame. Dal punto di vista della rete fisica l'IP datagram è un blocco di dati. La rete fisica ignora cioè come tali dati vengano utilizzati dall'IP. Quindi, il primo compito di IP è quello di decidere come costruire il datagram affinché possa essere trasmesso in un frame fisico. L'ideale sarebbe di poter mettere un singolo datagram in ogni frame, ottimizzando così la trasmissione e semplificando la logica. Ma quale frame? Quello della rete di partenza? Quello della rete di arrivo? E se durante la trasmissione il datagram deve passare attraverso più reti con MTU differenti? Il punto è che non c'è modo di fare una scelta che assicuri di avere un datagram per frame. D'altra parte internet ha come obiettivo quello di svincolarsi dalle caratteristiche fisiche delle varie reti interconnesse fra loro. E allora? La soluzione adottata è molto semplice. Le dimensioni del datagram sono scelte convenzionalmente secondo una logica del tutto indipendente dalle MTU delle singole reti fisiche, dopodiché, a seconda della rete in

cui il datagram deve passare, questo è spezzato in più pezzi di dimensioni inferiori alla MTU della rete fisica, detti frammenti (fragment).

 Il datagram è anch'esso un frame, che potremmo chiamare logico per distinguerla da quello usata da una specifica rete fisica per trasmettere i dati. Come tale anch'esso è formato da una intestazione e da un'area dati. All'atto della frammentazione, ogni frammento viene costruito replicando l'header del datagram, modificandone alcuni campi che vedremo in seguito, e aggiungendo a questo un pezzo dell'area dati originaria. L'aspetto più importante di questo meccanismo è che il riassemblaggio dei frammenti non viene effettuato quando i vari frammenti rientrano in una rete fisica ad alto MTU, ma sempre e comunque presso l'host di destinazione. Così, se due reti con MTU uguale a 1.500 ottetti sono separate da una rete con MTU più bassa, per esempio 500 ottetti, i frammenti che arriveranno a destinazione saranno di soli 500 ottetti. In questo caso la frammentazione avviene nel primo gateway mentre il riassemblaggio avviene solo nell'host di destinazione. Il protocollo IP richiede che sia gli host che i gateway siano capaci di gestire datagram di almeno 576 ottetti. In aggiunta, questi ultimi devono essere capaci anche di gestire datagram grandi quanto l'MTU più grande tra quelle delle reti a cui sono connessi. Ricordiamo che un gateway, per definizione, ha almeno due connessioni e quindi almeno due indirizzi IP.

Il punto debole di questo meccanismo è che la perdita di anche un solo frammento comporta la perdita dell'intero datagram. Dato che ogni frammento è trasmesso indipendentemente, passare attraverso reti a bassa MTU comporta un'elevata frammentazione anche nelle reti a maggiore MTU e comunque aumenta i rischi di perdita dei dati. Quando un frammento arriva a destinazione, e non è detto che il primo arrivi per primo, l'host fa partire un timer. Se questo scade prima che tutti i frammenti siano arrivati, il sistema cancella tutti i frammenti e considera perduto il datagram. Il concetto di timer e di tempi è estremamente importante per l'IP ed è spesso usato per ottimizzare la rete. Per esempio, ogni datagram ha una scadenza. Se il datagram è ancora all'interno della rete quando il suo tempo è scaduto, esso viene cancellato definitivamente. Lo scopo è quello di evitare che un pacchetto possa restare all'infinito in internet a causa di un errore in una routing table. Queste tabelle infatti servono a gestire il processo di instradamento del pacchetto nella rete. Se una o più tabelle sono sbagliate, si potrebbero creare cammini chiusi in cui i datagram potrebbero rimanere intrappolati. Veniamo finalmente al formato del datagram. Come si è già detto esso è composto di un'intestazione e di un'area dati. L'area dati contiene semplicemente una parte dei dati da trasmettere. Questo in quanto il datagram è piccolo mentre l'oggetto da trasmettere può essere anche molte centinaia di Kilobyte, se non addirittura migliaia, come per esempio un'immagine o un file compresso. L'intestazione è invece alquanto più complessa. Vediamola in dettaglio.

Struttura dei Datagram.

I primi 4 bit contengono la versione del protocollo IP che è stato utilizzato per creare il datagram. Infatti, come spiegato nella prima parte di questo corso, il tutto funziona se e solo se tutti seguono le stesse regole alla lettera. D'altra parte le convenzioni, e di conseguenza i protocolli, seguono un processo di evoluzione, per cui un datagram creato con una versione più recente potrebbe creare problemi a un protocollo più vecchio se questi non avesse modo di accorgersene in tempo. I 4 bit successivi danno la lunghezza dell'intestazione misurata in parole da 32 bit. Questa è necessaria agli algoritmi usati per leggere il datagram (parsing algorithms). Dato che i campi dell'intestazione potrebbere non risultare un multiplo intero di 32, è necessario porre alla fine dell'intestazione un campo di riempimento. Inoltre il programma di ricezione ha bisogno di conoscere anche la lunghezza totale del datagram, cioè la lunghezza dell'intestazione più quella dell'area dati. Questa è memorizzata nei bit dal 16 al 31 inclusi, e il suo valore è espresso in ottetti, al contrario del precedente. Poichè il campo è lungo 16 bit, il datagram non può essere più grande di 216 ottetti, cioè 65.535 byte.

Il campo tra la lunghezza dell'intestazione e quella totale del datagram identifica il tipo di servizio che va offerto al pacchetto, ed è formato da un campo di 3 bit che specifica l'importanza che va data al datagram, e da tre campi da 1 bit ciascuno che identificano il tipo di trasporto desiderato per questo pacchetto. Purtroppo questo campo non può essere sempre preso in considerazione da tutte le reti, in quanto non sempre la rete fisica è in grado di soddisfare le richieste di priorità e trasporto memorizzate in questo campo. Per cui esso viene considerato una sorta di raccomandazione alla rete, piuttosto che un vero obbligo. In ogni caso il campo di priorità può contenere valori da 0 a 7. Lo zero è il valore di base di un normale pacchetto, mentre il 7 rappresenta la richiesta di precedenza più elevata, e va usato per i datagram che contengono dati per il controllo della rete stessa. I tre bit relativi al tipo di trasporto servono a definire il livello di qualità relativo al trasferimento del pacchetto. Se impostati a uno, essi richiedono rispettivamente: di evitare al massimo ritardi nel recapitare il pacchetto al destinatario, di fornire la massima capacità di trasferimento, e di garantire un'elevata affidabilità durante il trasporto. Ovviamente è estremamente difficile poter fornire tutti e tre questi servizi contemporaneamente. Spesso la rete non riesce a garantirne neanche uno solo.

I tre campi successivi vengono utilizzati nel meccanismo di frammentazione spiegato poco fa, e in particolare sono quelli che permettono all'host che riceve i vari frammenti di riassemblare il tutto per ottenere il datagram originario. Essi sono assolutamente necessari in quanto non è prevista alcuna comunicazione tra il mittente e il destinatario su come ricomporre il datagram, tanto più che la frammentazione finale può essere il risultato di più frammentazioni successive. Inoltre i vari frammenti possono arrivare in qualunque ordine, dato che possono avere seguito cammini differenti. Dulcis in fundo, anche se l'intestazione di ogni frammento è ottenuta da quella del datagram originale, il quarto campo dell'intestazione di un frammento contiene la sua lunghezza totale, e non quella di tutto il datagram. Quest'ultima informazione deve essere calcolata dal destinatario in qualche modo. Ed ecco il perché di questi tre campi.

Il primo campo serve a identificare univocamente il datagram ed è lungo 16 bit. Tutti i frammenti che appartengono a uno stesso datagram hanno lo stesso identificativo. Il secondo campo è una maschera di 2 bit che controlla il meccanismo di frammentazione. Il primo bit specifica se il datagram può essere frammentato: se impostato a uno, la frammentazione non è permessa. Il secondo bit serve a marcare l'ultimo frammento. Vedremo tra un attimo a cosa serve. Il terzo campo contiene la posizione dei dati del frammento nel blocco originale di dati misurato in parole da 64 bit. Questo campo si chiama fragment offset. Per esempio, se un frammento ha un offset 7, vuol dire che il primo bit dei suoi dati corrisponde al quattrocentoquarantanovesimo bit dei dati del frammento originale, dato che 7 * 64 + 1 fa appunto 449. A questo punto è chiaro come si può ottenere la lunghezza totale del datagram originario. Basta sommare l'offset e la lunghezza totale dell'ultimo frammento, riconoscibile grazie al secondo bit del campo di controllo.

Il campo successivo, posto a partire dal 64° bit dell'ntestazione, è lungo un byte e serve a stabilire quanto a lungo un datagram può rimanere nella rete. È cioè il campo che specifica la scadenza di un datagram di cui avevamo accennato in precedenza. L'idea originaria era che tale campo contenesse il numero massimo di secondi che il pacchetto potesse restare nella rete. Tuttavia, data l'evidente difficoltà di sincronizzare gli orologi di tutti gli hosts e i gateway della rete, si è deciso di semplificare il meccanismo come segue: ogni gateway che processa il pacchetto decrementa il campo di uno quando questo arriva e memorizza il tempo di arrivo. Se il pacchetto non riparte subito ma rimane in attesa nel gateway, il valore di questo campo viene ulteriormente decrementato di una unità per ogni secondo di attesa. Come il campo arriva a zero, il datagram viene cancellato dalla rete e un messaggio di errore viene rispedito al mittente.

Il campo seguente, lungo 8 bit, identifica il protocollo di alto livello utilizzato che ha generato i dati contenuti nel datagram, e definisce di fatto il loro formato. Ne riparleremo in seguito, quando vedremo i protocolli applicativi.

Abbiamo quindi un campo di controllo di 16 bit che serve a verificare l'integrità dell'intestazione, e che utilizza il meccanismo di checksum ben conosciuto nel mondo del software. In suo valore è la somma complementata a uno delle parole da 16 bit che compongono l'intestazione, addizionate con il metodo del complemento a uno.

Quindi vengono gli indirizzi IP del mittente e del destinatario, ognuno lungo 32 bit. Di tali indirizzi e del loro scopo abbiamo parlato esaustivamente nella seconda e terza parte di questo corso.

Per finire abbiamo un campo di lunghezza variabile che può contenere varie opzioni, e quindi il campo di riempimento di cui abbiamo già parlato. Queste opzioni non sono presenti in tutti i datagram e vengono usate prevalentemente nelle verifiche e nella identificazione dei problemi della rete.

 

L’instradamento tra Client e Server con TCP/IP

Parliamo ora di due aspetti fin qui solo accennati: i meccanismi di instradamento dei pacchetti (routing) e la gestione degli errori. Iincominceremo a salire nella torre dei protocolli internet, introducendo il primo protocollo che si poggia sull'IP, e precisamente lo User Datagram Protocol (UDP). Come vedremo si tratta ancora di un protocollo molto legato all'IP, ma comunque considerato al di sopra di questo.

Come abbiamo già detto in precedenza, IP è un protocollo connectionless. Questo vuol dire che non esiste un collegamento diretto tra i due host che si scambiano dati, bensì una rete di connessioni attraverso la quale si possono identificare vari potenziali cammini da un host all'altro. Il cammino attraverso il quale i dati giungono all'host destinatario è scelto dinamicamente e può variare per ogni singolo pacchetto di dati.

Tale scelta non avviene quando il pacchetto parte, ma è il risultato di numerose decisioni prese a ogni singolo gateway. Per questo motivo i gateway sono detti anche router. Tali scelte possono dover tenere conto di molti elementi, quali la priorità del messaggio, il carico di rete, la capacità delle reti intermedie, e via dicendo. La base tuttavia del meccanismo sono le tabelle di instradamento (routing table). Vediamo di che si tratta.

Consideriamo prima una singola rete fisica. Se un host vuole spedire un messaggio a un altro host nella stessa rete, non deve far altro che incapsulare il messaggio in un datagramma IP fornendo quindi l'indirizzo IP del destinatario, e passare il tutto al livello inferiore. Questi provvederà a ricavare dall'indirizzo IP l'identificativo del destinatario nella rete fisica, a incapsulare il datagramma in un frame, e a spedire direttamente il tutto all'host finale . Questa tecnica si chiama instradamento diretto (direct routing).

Vediamo adesso quello che succede quando abbiamo due reti interconnesse tramite un gateway. L'host mittente si accorge che il destinatario non è nella sua rete fisica, dato che il network id del suo indirizzo IP è diverso da quello a cui deve spedire il datagramma. Spedisce allora il messaggio al gateway passando sia il datagramma che l'indirizzo IP del gateway al livello inferiore. Il

messaggio arriva quindi direttamente al gateway che estrae l'indirizzo IP del destinatario, si accorge che fa parte della seconda rete a cui è connesso, e spedisce quindi il tutto all'host finale attraverso la rete fisica. Questa tecnica si chiama di instradamento indiretto (indirect routing).

In questo secondo caso la tabella di instradamento è semplice, dato che il gateway ritrasmette sempre i messaggi che devono andare da una rete all'altra attraverso la rete fisica. Se invece abbiamo più gateway tra i due host, ogni gateway, tranne l'ultimo, dovrà spedire il messaggio a un altro gateway.

Per far questo userà appunto la tabella di instradamento che fornisce per ogni possibile rete destinataria finale l'indirizzo IP del gateway successivo. È da notare che queste tabelle non contengono di solito gli indirizzi IP di tutti i possibili host destinatari, cosa che sarebbe fisicamente impossibile, bensì gli indirizzi delle reti raggiungibili a partire da quel gateway. Esiste poi la possibilità di specificare un gateway di default e cammini specifici per host speciali. La prima cosa è molto comune, mentre la seconda è usata solo in casi eccezionali. La logica di instradamento è quindi quella riportata nel diagramma.

La gestione dei messaggi di errore

Come si può facilmente capire dal meccanismo di instradamento appena spiegato, non è possibile sapere se il destinatario effettivamente esiste fintanto che il datagramma non arriva all'ultimo gateway. In generale l'IP non contiene grossi meccanismi di verifica, ed è per questo che è detto "inaffidabile". Esso richiede quindi un protocollo ausiliaro per l'emissione di messaggi di errore in rete, che permettano ai protocolli di livello superiore di implementare una logica più affidabile e robusta. Tale protocollo è chiamato Internet Control Message Protocol (ICMP).

L'ICMP è considerato parte integrante dell'IP ed è sostanzialmente un protocollo per la segnalazioni di errori il cui utente principale è l'IP stesso. Solo in casi particolari l'ICMP arriva a informare dell'errore eventuali livelli superiori all'IP. In ogni caso cosa fare quando avviene un errore non spetta all'ICMP, ma ai processi che se ne avvalgono. L'ICMP informa sempre l'IP mittente, non i vari gateway intermedi. Questo in quanto del cammino percorso da un datagramma non rimane traccia, per cui l'unico possibile destinatario di un messaggio di errore è solo chi ha generato il datagramma. Inoltre, dato che i datagrammi ICMP viaggiano incapsulati in datagrammi IP, come un qualunque messaggio di livello superiore, essi sono soggetti alle stesse limitazioni in termini di affidabilità di qualunque altro messaggio spedito via TCP/IP. Non analizzeremo in dettaglio tutti i datagrammi ICMP, anche perché ognuno può avere una struttura differente. Diremo solamente che l'intestazione di un datagramma ICMP contiene sempre almeno tre campi: il tipo di messaggio, un codice di errore, e una somma di controllo.

Il livello di Trasporto

Come già detto, la torre Internet si può schematizzare più o meno su quattro livelli. Alla base della torre sta l'hardware che rappresenta la rete vera e propria. Sopra a questo sta il primo livello, quello cioè di interfaccia alla rete fisica, detto appunto Network Interface o anche Data Link. I protocolli a questo livello si scambiano blocchi di dati chiamati frame, la cui struttura è strettamente legata alle caratteristiche hardware della rete stessa. Al di sopra di questo livello c'è il livello di interconnessione fra reti, ovverosia il livello dell'IP la cui unità di scambio dati è appunto il datagramma IP, mentre il terzo livello è quello detto di Trasporto. Concettualmente è a questo livello che si pongono sia il TCP che appunto l'UDP. L'unità di scambio dati al terzo livello si chiama pacchetto (transport packet). Il quarto livello è infine quello Applicativo, al quale vengono scambiati i messaggi applicativi (message e data stream).

Abbiamo visto come l'IP permette di scambiare datagrammi fra host, cioè a livello di macchine. Tuttavia non è certo la macchina il destinatario finale dei dati che fluiscono nella rete, bensì le applicazioni e i programmi che girano su di essa. I moderni sistemi operativi permettono di far girare più processi contemporaneamente, e comunque questi non hanno le caratteristiche di permanenza che ha invece un host. Un programma infatti è un componente dinamico e temporaneo in un sistema. Non è quindi pensabile di poter associare a un processo un identificativo fisso come si fa con gli host e gli indirizzi IP. Un processo infatti non ha un identificativo univoco in un sistema, dato che ogni volta che viene lanciato esso può assumere un identificativo diverso. Inoltre non è detto che gli stessi dati siano sempre processati dalla stessa applicazione. Per esempio, oggi potrei voler usare un certo programma per gestire la mia posta elettronica, domani potrei decidere di usarne un altro, e non è sicuramente pensabile che si debba informare tutta la rete ogni volta che si decide di cambiare l'applicazione che gestisce un certo tipo di dati. Quindi, più che il processo, quello che è importante identificare è la funzione, come per esempio, trasferire file oppure spedire posta elettronica. Lo scopo dell'UDP è appunto quello di permettere di distinguere in un singolo host più destinatari per i dati che arrivano dalla rete. Ma come?

Facciamo un attimo una digressione. Se io devo stampare un file cosa faccio? Collego al mio computer una stampante, attivo il driver corrispondente, e uso una applicazione o un comando del sistema operativo per lanciare l'ordine di stampa. Se ora stacco la stampante e ne attacco un'altra alla stessa porta non devo far altro che cambiare il driver per continuare a lavorare senza che il sistema si sia accorto di niente. Se poi le due stampanti usano lo stesso driver generico devo solo staccare e riattaccare fisicamente le stampanti senza modificare il sistema. In generale, tutto lo scambio di dati da e verso un computer avviene attraverso porte di I/O. Ogni applicazione accede la porta che gli serve in modo dinamico. La periferica di I/O non ha bisogno di sapere con quale applicazione sta parlando: la porta fa da schermo fra i due. L'UDP fa una cosa analoga. Esso permette di associare a un indirizzo IP più punti di ingresso e di uscita virtuali, detti protocol port. Queste porte si comportano un po' come quelle di I/O di un computer. Ogni porta è identificata da un numero intero positivo e i processi possono chiedere al sistema l'accesso a tali porte. Quando un processo accede una porta, esso si mette in attesa dei dati sulla stessa. Il meccanismo è cioè sincrono. Inoltre, se dei dati arrivano a una porta alla quale non si è agganciato ancora un processo, questi vengono mantenuti in memoria nell'ordine di arrivo. Si dice cioè che le porte hanno un buffer. A questo punto, sia il processo mittente che quello destinatario sono univocamente identificati dall'indirizzo IP dell'host su cui girano e dal numero di porta che utilizzano per la trasmissione in rete. Tale associazione è tuttavia

dinamica, e così come più applicazioni possono stampare sulla stessa stampante purché non contemporaneamente, così più processi possono attaccarsi uno alla volta alla stessa porta ed essere visti come lo stesso destinatario dalla controparte mittente. Questo permette di spedire un file di testo con un word processor, e subito dopo spedire un file binario, per esempio un file ZIP, con un comando di sistema. Il tutto sempre attraverso la stessa porta e con lo stesso destinatario in termini di host e di processo.

Come abbiamo visto nel caso dell'IP e dei vari protocolli di rete, anche il datagramma UDP è formato da una intestazione (header) e da una parte dati. Esso è inoltre incapsulato in un datagramma IP il quale a sua volta è contenuto in un frame della rete fisica.

Al contrario tuttavia di quello IP, l'header UDP è molto più semplice. Esso è formato dal numero di porta del mittente, da quello del destinatario, dalla lunghezza del messaggio UDP, sia dei dati che dell'intestazione, e da una somma di controllo (checksum) per la verifica dell'integrità dei dati. Infatti, anche l'UDP, come l'IP, è un protocollo cosiddetto "inaffidabile". Questo vuol dire che un messaggio UDP può andare perso, essere duplicato, o arrivare nell'ordine sbagliato. L'UDP non fa alcun controllo al riguardo. L'affidabilità della comunicazione è infatti affidata a i protocolli di livello più elevato. Tutti i campi dell'intestazione sono lunghi 16 bit. Benché il formato del datagramma UDP sia alquanto semplice, la sua gestione può essere un po' più complessa. Il punto riguarda la somma di controllo. Questo valore è opzionale e, al contrario di quello che succedeva con la somma di controllo nel datagramma IP, esso non è relativo solo all'intestazione ma a tutto il datagramma, compresa la parte dati. Questo vuol dire che tale campo rappresenta l'unico elemento di controllo a livello IP e UDP dell'integrità dei dati arrivati. Se esso non viene utilizzato, il campo va posto a zero. Questo in quanto la somma di controllo segue la logica a complemento uno. Il che vuol dire che se la somma calcolata è zero, essa può essere memorizzata come 16 bit impostati a uno, dato che in tale logica un valore con tutti i bit a uno e uno con tutti i bit a zero rappresentano lo stesso numero. Quindi: se il campo è a zero, vuol dire che non è stato utilizzato; se viceversa ha tutti i bit ad 1, vuol dire che la somma era zero.

La somma di controllo, tuttavia, per ragioni pratiche, non riguarda solo il datagramma UDP, ma viene calcolata anche utilizzando alcune informazioni addizionali. Queste formano il cosiddetto pseudo-header.

In pratica, quando si deve calcolare il checksum UDP si mette davanti al datagramma UDP un altro blocco di dati che contiene l'indirizzo IP del mittente e del destinatario, il codice del protocollo UDP (17), e la lunghezza del datagramma UDP. Il motivo di questa tecnica risiede nel fatto che, per verificare se un messaggio UDP è arrivato al giusto destinatario, non basta verificare il numero di porta, ma anche l'indirizzo IP dell'host in cui gira il processo che è collegato a quella porta. Il datagramma UDP contiene tuttavia solo il numero di porta, per cui il controllo fornito da una somma sul solo datagramma non potrebbe realmente verificare che il destinatario dei dati è quello giusto.

Questa tecnica ha tuttavia un prezzo: gli indirizzi IP fanno parte appunto del livello internet, non di quello di trasporto. Perché l'UDP conosca tali informazioni è necessario violare una legge fondamentale dei protocolli di comunicazione, e cioè che ogni livello della torre deve gestire i suoi dati senza esportarli agli altri livelli a cui offre, o da cui riceve, servizi. Questo vuol dire che la separazione tra UDP ed IP non è così pulita come dovrebbe essere, ma che i due protocolli sono in qualche modo legati tra loro. D'altra parte i vantaggi in termini di controllo e semplicità di implementazione sono tali che si è deciso di fare un'eccezione ai principi dell'architettura. Da notare che la pseudo-intestazione serve solo a calcolare la somma di controllo. Essa non viene fisicamente trasmessa con il datagramma UDP, dato che le informazioni che contiene fanno già parte dell'intestazione del datagramma IP in cui quello UDP sarà incapsulato.

Proprietà funzionali del protocollo.

Se l’IP rappresenta il braccio del TCP/IP, il TCP ne rappresenta la mente. Il primo si limita a spedire rapidamente i dati che gli arrivano senza preoccuparsi troppo se qualcosa va male. Il secondo si occupa invece di controllare che l’informazione passatagli dai livelli superiori arrivi correttamente a destinazione. Insieme sono sicuramente una coppia molto affiatata.

In questo articolo useremo il termine applicazioni per indicare tanto i protocolli applicativi come FTP o SMTP, quanto i programmi applicativi veri e propri, salvo indicazione contraria. Indicheremo inoltre con il termine utente di un servizio colui che utilizza tale servizio, sia esso direttamente una persona, un’applicazione, o un protocollo. Per esempio, il TCP è un utente dell’IP.

C’è subito da dire due cose importanti sul TCP. La prima è che lo standard del TCP non definisce né l’implementazione dello stesso, né le modalità con cui un’applicazione accede a i servizi di questo protocollo. Esso definisce solamente le caratteristiche di tali servizi, per cui si possono trovare molte differenti implementazioni del TCP, ognuna con la propria interfaccia applicativa. Per chi non programma ricordo che un’interfaccia applicativa o API (Application Programming Interface) non è altro che l’insieme delle funzioni, delle istruzioni, dei parametri e dei blocchi di controllo che vengono utilizzati dai programmatori per accedere ai servizi di un sistema. Per esempio, se ho un sistema di posta elettronica potrei definire un’API basata su due funzioni, una chiamata spedisci, e una chiamata ricevi . Per ogni funzione sarebbero poi da definire quali informazioni sono da passare al momento dell’utilizzo (parametri in ingresso), quali si ottengono una volta espletato il servizio (parametri di ritorno), eventuali codici di errore, e le regole di utilizzo delle singole funzioni. Il motivo che sta alla base della scelta di non standardizzare l’interfaccia con il TCP è che in molti casi questo protocollo è direttamente definito nel sistema operativo, o comunque fa parte del cosiddetto corredo di base di un sistema, per cui si è voluto evitare di forzare una sintassi che potesse essere in contrasto con quella nativa del sistema ospite. Il secondo punto fondamentale è che il TCP è stato definito per funzionare su un qualsiasi sistema di trasmissione dati a pacchetto, e non necessariamente solo sull’IP. Di fatto esso può essere poggiato, per esempio, direttamente sopra una rete Ethernet senza bisogno di un livello Internet intermedio.

Ma qual è lo scopo del TCP nell’architettura internet? Il protocollo non fornisce le garanzie di affidabilità e robustezza necessarie per implementare un sistema di trasmissione dati sicuro e di facile gestione. L’IP è inaffidabile e benché schermi lo sviluppatore dalla conoscenza della rete fisica, fornisce ancora una visione di livello troppo basso del sistema di reti interconnesse. Questo vuol dire che l’IP è troppo complesso per essere utilizzato direttamente dalle applicazioni. Per avere un protocollo di trasmissione affidabile abbiamo bisogno di gestire tutte le possibili situazioni di errore, la duplicazione o la perdita dei pacchetti, la caduta delle connessioni o di un router, e via dicendo. Se le

applicazioni utilizzassero direttamente i servizi dell’IP, ognuna di esse dovrebbe implementare una serie alquanto complessa di algoritmi e servizi per tenere conto di tutto ciò. A parte il fatto che esistono relativamente pochi programmatori in grado di far questo fra gli svariati milioni di sviluppatori di applicazioni, nella maggior parte dei casi si tratterebbe di reinventare ogni volta la ruota. In generale questi problemi, seppure complessi, sono abbastanza standard, per cui si è pensato di poggiare sui sistemi di trasmissione a pacchetti un protocollo affidabile che potesse essere implementano da sviluppatori altamente specializzati, lasciando così agli altri la possibilità di concentrarsi sulla logica applicativa piuttosto che sugli aspetti specifici della trasmissione dei dati a basso livello.

Vediamo allora quali sono le caratteristiche principali del TCP, eventualmente comparate a quelle dell’IP.

Innanzi tutto il TCP fornisce una visione dei dati di tipo a flusso (data stream), cioè i dati sono ricevuti in sequenza e nello stesso ordine con il quale sono stati trasmessi. A questo livello cioè, l’utente del TCP spedisce i dati come un singolo flusso di byte e nello stesso modo li riceve. Nell’IP avevamo invece la divisione dei dati in pacchetti che potevano subire un’ulteriore frammentazione se si trovavano a passare attraverso reti caratterizzate da una soglia molto bassa sulle dimensioni dei frame fisici. I pacchetti potevano inoltre arrivare in ordine sparso rispetto a quello di trasmissione.

Secondo punto: nell’IP non si sa mai a priori il cammino che effettua un pacchetto. Il TCP fornisce al suo utente una visione del collegamento come se esso fosse una linea dedicata. Ovviamente sotto sotto il meccanismo è ancora quello a pacchetti, ma la cosa è schermata agli utilizzatori del TCP. Tale caratteristica è detta vitual circuit connection, cioè circuito di connessione virtuale. Il TCP si basi sul concetto di connessione, piuttosto che su quello di indirizzo come fa invece l’IP. Una connessione, per definizione, richiede la definizione di due punti piuttosto che di uno solo, detti punti terminali o estremi della connessione (endpoint). Parleremo anche di interlocutori per indicare gli utenti posti agli estremi della connessione.

Terzo punto: abbiamo visto che l’IP divide i dati in pacchetti che vengono costruiti sulla base di esigenze di trasmissione legate alle varie reti fisiche su cui si poggia il sistema. D’altra parte le applicazioni dividono i dati in funzione delle esigenze applicative. Per esempio, un’applicazione di posta elettronica può considerare una lettera da 8.000 caratteri una singola unità dati, mentre un protocollo per la gestione della rete può avere l’esigenza di spedire tanti piccoli messaggi di non più di 16 byte l’uno. Il TCP permette di disaccoppiare il modo di dividere i dati delle applicazioni da quello dell’IP. Così la lettera di cui sopra viene prima spezzata in tante parti, spedita via IP e poi ricomposta dal livello TCP del destinatario, mentre per i messaggi di controllo avviene il contrario: prima vengono accumulati in un singolo pacchetto, e poi rispezzettati presso il destinatario. Questo meccanismo è detto buffered transfer. Naturalmente può sorgere l’esigenza di forzare la trasmissione dei dati anche se il buffer non è pieno. Per esempio, se serve sapere se un certo sistema è attivo o meno manderò prima un messaggio di interrogazione, e solo una volta ricevuta la conferma incomincerò a spedire gli altri dati. Dato che il messaggio di interrogazione è più piccolo del buffer, esso non verrebbe realmente spedito dal TCP fintanto che questi non è stato riempito. È quindi necessario forzare la trasmissione del primo messaggio (push) se si vuole evitare di attendere inutilmente la risposta a un messaggio che in realtà non è mai partito.

Quarto punto: per quanto intelligente, il TCP si preoccupa di trasferire i dati che gli vengono passati senza entrare in merito a il loro significato dal punto di vista applicativo. In che modo il flusso di dati vada interpretato semanticamente è responsabilità delle due applicazioni che utilizzano la connessione TCP per cooperare. Questo vuol dire che se un’applicazione manda alla sua controparte una serie di indirizzi, questi arriveranno uno di seguito all’altro nel giusto ordine, ma senza alcuna garanzia che ogni buffer contenga un numero intero di indirizzi. Sta all’applicazione ricomporre un indirizzo capitato a cavallo di due buffer consecutivi. Si parla quindi di flusso senza struttura (Unstructured Stream).

Quinto e ultimo punto: le connessioni TCP permettono il trasferimento contemporaneo dei dati in entrambe le direzioni, quello che nel gergo delle comunicazioni si chiama una connessione full-duplex. Si hanno cioè due flussi che scorrono indipendentemente in direzioni opposte, senza interagire fra loro. Le applicazioni hanno comunque la possibilità di passare alla modalità half duplex semplicemente bloccando uno dei due flussi di dati.

Ma in che modo il TCP garantisce quella affidabilità che manca all’IP? Il meccanismo di base utilizzato sia dal TCP che da molti altri protocolli cosiddetti "affidabili" è quello della ritrasmissione in caso di mancata conferma (positive acknowledgement with retrasmission). Si tratta di un meccanismo concettualmente semplice: ogni qual volta uno dei due interlocutori di una connessione spedisce dei dati, questi attende una conferma dell’avvenuta ricezione. Se questa arriva entro un tempo stabilito viene spedito il pacchetto successivo, altrimenti l’applicazione rispedisce quello precedente. Tale tempo viene misurato con un timer che viene fatto partire ogni volta che un pacchetto è spedito. Questo meccanismo risolve il problema dei pacchetti persi o danneggiati, ma può crearne un altro. Supponiamo che a causa di problemi di saturazione della rete un pacchetto ci metta molto più tempo del previsto ad arrivare. A questo punto il mittente, non vedendosi arrivare indietro la conferma ne rispedisce una copia. Succede così che il destinatario riceve a una certa distanza l’uno dall’altro due copie dello stesso pacchetto. Il problema della duplicazione dei pacchetti viene risolto facendo numerare sequenzialmente al mittente tutti i pacchetti da spedire e facendo verificare al destinatario la sequenza ricevuta. Naturalmente questo non vale solo per i messaggi ma anche per le conferme agli stessi. Infatti anche una conferma potrebbe venire erroneamente duplicata. Per evitare questo ogni conferma riporta il numero di sequenza del messaggio a cui si riferisce, permettendo così al mittente di verificare che a ogni messaggio spedito corrisponda una e solo una conferma di ricezione. È un po' lo stesso meccanismo di una raccomandata con ricevuta di ritorno.

In realtà gli algoritmi utilizzati dal TCP sono un po' più complicati, e tengono conto di tutta una serie di situazioni che si possono verificare. Senza contare che il tempo di attesa prima della ritrasmissione è un punto chiave di tutto il discorso. Se si attende troppo poco si rischia di generare un sacco di duplicati inutili, saturando per giunta la rete, mentre se si attende troppo si rischia di abbassare notevolmente e inutilmente le prestazioni della trasmissione dei dati, rallentando le applicazioni alle estremità della connessione.

Il meccanismo della conferma di ricezione con ritrasmissione ha inoltre un grosso svantaggio. Anche se i tempi di attesa sono scelti in modo ottimale, esso causa un notevole sottoutilizzo della rete. Infatti, indipendentemente dalla capacità della rete, i due interlocutori passano la maggior parte del tempo attendendo le varie conferme. È un po' come avere un tubo nel quale vengono fatte cadere una a una delle palline numerate in sequenza. All’altra estremità del tubo c’è una cesta poggiata su un prato, un po' distante dal foro di uscita. Se la pallina cade nella cesta fa rumore, altrimenti cade nel prato e non si sente niente. Se ogni volta che metto una pallina nel tubo aspetto di sentire il rumore che mi conferma che la pallina è caduta nel cesto, il tubo resta per la maggior parte del tempo vuoto. Una tecnica di ottimizzazione usata dal TCP per rendere più efficiente il meccanismo appena descritto è quella delle finestre di scorrimento (sliding window). Funziona più o meno in questo modo. Immaginate di immettere nel tubo una sequenza di dieci palline senza attendere che la prima sia arrivata. Come si sente il primo flop si aggiunge un’undicesima pallina, e poi una dodicesima e così via. Se si salta un flop si reinserisce una pallina con lo stesso numero di quella che non è arrivata, tanto il destinatario può comunque riordinare le palline utilizzando i numeri scritti sopra. Il numero di palline che compongono il trenino da spedire indipendentemente dalla ricezione del flop si chiama dimensione della finestra di scorrimento (sliding window size). Se si sceglie una dimensione tale da riempire tutto il tubo nella sua lunghezza si sfrutta al massimo la capacità dello stesso.

In pratica questo sistema divide la sequenza di pacchetti in tre fasce. La prima è rappresentata dai pacchetti spediti e di cui si è avuta la conferma di ricezione. La seconda è formata dai pacchetti spediti ma dei quali non si sa ancora niente, e la terza è formata dai pacchetti ancora da spedire. Con questa tecnica il TCP mantiene un timer per ogni singolo pacchetto che appartiene alla seconda fascia. Il nome "Finestra di scorrimento" deriva dal fatto che è come se ci fosse una finestra ampia quanto il trenino di pacchetti che possono essere spediti senza attendere la conferma dell’avvenuta ricezione che scorre in avanti un pacchetto alla volta ogni qual volta arriva una conferma. Anche in questo caso, come in quello del tempo di attesa prima di ritrasmettere un pacchetto, le dimensioni della finestra di scorrimento rappresentano un fattore critico per determinare l’efficenza del sistema. In generale, se le dimensioni della finestra sono maggiori del tempo di attesa per il singolo pacchetto, allora la finestra continua a scorrere regolarmente senza interruzioni, salvo nel caso di ritrasmissioni, e la capacità di carico della rete viene sfruttata al massimo.

Assegnazione delle porte di comunicazione

Affinché infatti due applicazioni possano comunicare fra di loro esse debbono conoscersi e il sistema di trasmissione che le serve deve sapere a chi effettivamente vanno recapitati i dati. È evidente che non basta l'indirizzo IP, che identifica univocamente un host nella rete. Basti pensare che un PC collegato in rete ha in genere un solo indirizzo IP, a meno che non sia collegato a più reti fisiche, come per esempio un gateway. Se una lettera viene spedita via rete a un certo indirizzo come fa TCP a sapere a quale applicazione deve far arrivare i dati? Un sistema potrebbe essere quello di assegnare un identificativo a ogni singola applicazione, ma come garantire allora l'univocità dell'identificativo? Senza contare che questo costringerebbe la controparte a sapere a priori tale valore per ogni possibile destinatario. Non è inoltre detto che un utente utilizzi sempre lo stesso programma per spedire o ricevere la posta elettronica. In realtà, più che la specifica applicazione, quello che è importante identificare è la funzione, come per esempio trasferire file oppure spedire posta elettronica.

La soluzione è quella di definire dei punti di ingresso e di uscita virtuali chiamati porte. Ogni porta rappresenta di fatto un punto di accesso a un'applicazione nel sistema. Si tratta in pratica di un'estensione del concetto di porta hardware. Un PC moderno, per esempio, può avere porte hardware parallele, seriali, video, audio e di vari altri tipi. Ad ogni porta possono essere attaccati dispositivi molto differenti. Per esempio, a una porta parallela è possibile attaccare una stampante, uno scanner, un'unità Cd-Rom oppure un'unità disco ad alta capacità. Tutti questi dispositivi non hanno bisogno di una porta specifica, ma possono utilizzare la stessa porta perché gestiscono flussi di dati simili, possono cioè usare lo stesso protocollo di base per la trasmissione dei dati. Ovviamente, a livello applicativo, ogni periferica darà ai propri dati una struttura differente. Questo vuol dire che i dati costruiti per una stampante non possono certo essere mandati a uno scanner. D'altra parte anche TCP non entra in merito della struttura applicativa dei dati, ma solo alle modalità di trasmissione degli stessi.

Ogni porta TCP è identificata da un numero. I numeri sotto il 256 sono utilizzati per le cosiddette "porte conosciute", cioè porte alle quali è stata assegnata una responsabilità ben precisa, mentre quelli al di sopra sono utilizzati per le assegnazioni dinamiche. Avremo per esempio una porta per i servizi di posta elettronica X.400 chiamata appunto X400 (103) alla quale faranno riferimento tutte le applicazioni che utilizzano tali servizi, oppure le due porte per il trasferimento dei file via FTP, una per il controllo (FTP, 21) e una per i dati (FTP-DATA, 20). Una lista delle porte conosciute attualmente assegnate è riportata nella RFC 1060, reperibile a ftp://ds.internic.net/rfc/rfc1060.txt Mentre in UDP la porta rappresenta un elemento sufficiente alla comunicazione, per cui il protocollo non fa altro che smistare i vari datagrammi nelle code dati (queue) associate alle varie porte . Una connessione è l'insieme di due punti, detti estremi della connessione (endpoint), ognuno identificato univocamente da due coordinate: l'indirizzo IP e il numero di porta. Una connessione è quindi rappresentata da ben quattro identificativi: gli indirizzi IP delle due macchine su cui girano le due applicazioni che si scambiano i dati, e i rispettivi numeri di porta. È importante capire che l'identificazione della connessione richiede tutti e quattro i valori, per cui la stessa porta con lo stesso indirizzo IP può essere condivisa simultaneamente da più connessioni senza creare alcun problema o ambiguità.

Ecco perché in TCP si pensa in termini di linea dedicata. È come se ci fosse un filo che lega univocamente i due interlocutori. Ogni interlocutore può avere più connessioni aperte nello stesso momento a partire dallo stesso capo purché non ce ne siano due con la stessa controparte. Il vantaggio è che una singola applicazione, per esempio di posta elettronica, necessita di una sola porta TCP per fornire servizi a molte macchine contemporaneamente attraverso differenti connessioni che condividono uno stesso estremo. Va tenuto presente che, anche se UDP e TCP usano gli stessi numeri per le porte, non esiste possibilità di confusione, dato che i pacchetti IP portano con sé l'identificativo del protocollo utilizzato che è ovviamente diverso per i due protocolli.

Affinché la connessione venga stabilita, entrambi gli estremi devono dare la loro autorizzazione. L'aggancio avviene nel seguente modo. Una delle due applicazioni che si vogliono connettere effettua un'apertura passiva (passive open), cioè informa il suo sistema che è disposta ad accettare una richiesta di connessione. TCP assegna all'applicazione un numero di porta. L'altra applicazione deve invece effettuare un'apertura attiva (active open), specificando l'indirizzo IP e la porta con la quale si vuole connettere. A questo punto i due livelli TCP stabiliscono la connessione e verificano che tutto sia a posto.

 

La gestione dei dati

Vediamo adesso come TCP gestisce i dati. Innanzi tutto, come già detto, TCP vede i dati come una sequenza non strutturata di ottetti, cioè byte, detto flusso di dati (data stream). Questo flusso viene diviso in segmenti ognuno dei quali viaggia di solito in un singolo pacchetto IP. Per aumentare l'efficienza della trasmissione, TCP utilizza una versione particolare del meccanismo a finestre di scorrimento spiegato sopra. Ricordo che questo meccanismo consiste nel mandare un gruppetto di dati prima di aver ricevuto la conferma di ricezione di ogni singolo pacchetto, in modo da tenere costantemente sotto carico la linea. Se infatti si dovesse attendere la conferma di ricezione per ogni singolo pacchetto prima di spedire il successivo la linea resterebbe per la maggior parte del tempo inutilizzata. Si dà insomma fiducia alla rete, partendo dal presupposto che la perdita di dati sia l'eccezione piuttosto che la regola.

Esistono tuttavia due importanti differenze tra il meccanismo base presentato prima e quello più sofisticato utilizzato effettivamente da TCP.

La prima è che l'unità base per i dati non è né il segmento né il pacchetto IP ma il singolo ottetto. Ogni ottetto viene numerato e TCP mantiene tre puntatori per ogni flusso di dati in uscita: uno che separa gli ottetti già spediti e arrivati felicemente a destinazione da quelli di cui non si hanno ancora notizie, uno che separa quelli già spediti da quelli che devono ancora essere spediti senza attendere la conferma di ricezione per i precedenti ottetti, e uno che separa questi ultimi da quelli che non possono essere spediti fintanto che la finestra non scorre in avanti. Una serie di informazioni speculari è mantenuta dal destinatario che deve ovviamente ricostruire il flusso di dati nel modo corretto indipendentemente dall'ordine di arrivo dei dati. Dato che una connessione è full-duplex, TCP manterrà quindi per ogni connessione due finestre di scorrimento, una per i dati in uscita e una per quelli in ingresso: un totale di quattro finestre per connessione considerando entrambi gli estremi. Esiste quindi un'asimmetria rispetto al meccanismo base dove l'unità dati utilizzata nella finestra di scorrimento era la stessa utilizzata nella trasmissione. Qui TCP utilizza il segmento come unità dati da trasmettere, mentre ragiona in termini di ottetti per quello che riguarda il meccanismo di ritrasmissione.

La seconda differenza è che le dimensioni della finestra di scorrimento non sono fisse ma variano nel tempo in funzione della capacità di ricezione del destinatario. Ogni conferma di ricezione che ritorna al mittente contiene una soglia di capacità (window advertisement) che contiene il numero di ulteriori ottetti che il destinatario è in grado di ricevere. In pratica questo meccanismo permette di adattare la finestra di spedizione alle dimensioni del buffer di ricezione. Si tratta cioè di un meccanismo di controllo del flusso dei dati che limita il numero dei dati in ingresso man mano che il buffer di ricezione si riempie, fino a poter interrompere momentaneamente la trasmissione nel caso che si sia raggiunta la massima capacità di ricezione del destinatario. Basta infatti che il destinatario mandi una soglia uguale a zero perché il mittente interrompa la spedizione degli ottetti fino all'arrivo di una conferma di ricezione contenente di nuovo una soglia maggiore di zero.

In realtà il mittente non smette del tutto di mandare dati. Innanzi tutto, se ci sono dati urgenti da spedire, il mittente informa comunque il destinatario di tale necessità trasmettendo un segmento con un indicatore di urgenza al suo interno. Questo permette al destinatario di prendere delle contromisure per ricevere comunque i dati urgenti, per esempio aumentando le dimensioni del buffer. In secondo luogo, è sempre possibile che la conferma con soglia positiva che dovrebbe far ripartire la trasmissione dei dati vada perduta. Per questo motivo il mittente prova ogni tanto a far partire un segmento per vedere se per caso il destinatario è di nuovo pronto a ricevere i dati.

Il controllo di flusso

Il controllo del flusso dei dati è un aspetto estremamente importante in un sistema in cui sono collegate macchine anche molto differenti fra loro per dimensioni e capacità di trasmissione . Per controllo del flusso si intende la possibilità di regolare dinamicamente la quantità di dati che vengono immessi nella rete. Non solo è importante che il destinatario possa regolare la velocità di spedizione in funzione della sua capacità di ricezione, ma è fondamentale che ogni gateway intermedio possa frenare il flusso dei dati che riceve per evitare di entrare in saturazione. Il meccanismo appena descritto della soglia di capacità permette di risolvere il primo problema, non il secondo. Quest'ultimo è detto congestione, ed è estremamente importante perché non tenerne conto vuol dire mandare in tilt la rete.

Lo standard TCP non prevede alcun meccanismo di controllo della congestione, lasciando agli implementatori di tale protocollo il non banale compito di sviluppare una logica capace di evitare questo tipo di problemi.

Per quello che riguarda i segmenti, il fatto che TCP sia libero di dividere il flusso in segmenti può a volte causare problemi dal punto di vista applicativo. Per esempio, supponiamo di implementare via TCP/IP un terminale remoto. Questo vuol dire che tutte le operazioni effettuate con la tastiera e il mouse su di una macchina (chiamiamola locale) saranno visibili su di un'altra macchina (remota) come se esse fossero state effettuate dalla tastiera e dal mouse della macchina remota. Non solo: sarà possibile vedere lo schermo della macchina remota all'interno di una finestra della macchina locale . Questo tipo di applicazioni è molto utile per esempio se per un qualche motivo la macchina da controllare non ha una sua tastiera oppure si trova in un locale non generalmente accessibile all'operatore. È evidente che affinché l'applicazione funzioni essa debba lavorare in tempo reale. Se cioè si preme il tasto T sulla tastiera locale, la lettera T deve apparire immediatamente sullo schermo della macchina remota, e quindi apparire anche all'interno della finestra locale che riproduce tale schermo. Lo stesso se si fa click sul pulsante di chiusura di una finestra. Ovviamente se TCP fosse libero di accumulare questi comandi per poi spedirli tutti in una volta l'applicazione sarebbe di difficile utilizzo. Infatti, se l'operatore decidesse di chiudere una finestra dello schermo remoto per accedere un'icona sottostante e TCP non spedisse il comando fintanto che il buffer di partenza non fosse pieno, non sarebbe possibile eseguire l'operazione successiva, cioè

aprire l'icona sulla scrivania del sistema. Per questo motivo TCP prevede la possibilità di forzare la spedizione del buffer (push). Questo tuttavia non è sufficiente. Se infatti TCP che riceve i dati accumulasse gli stessi nel buffer di ricezione prima di passarli all'applicazione destinataria saremmo punto e da capo. Per questo motivo, quando un segmento è forzato in uscita, TCP imposta a uno un certo bit nell'intestazione del segmento in modo che questi possa venire riconosciuto e immediatamente passato all'applicazione remota.

 

Assimetria di banda impegnata.

Abbiamo detto che il TCP utilizza il metodo della finestra di scorrimento per tenere la rete sempre impegnata al massimo della sua capacità e che esiste un'importante differenza tra il meccanismo generale e quello più sofisticato utilizzato effettivamente dal TCP. Tale differenza consiste in un'asimmetria rispetto al meccanismo base dove l'unità dati utilizzata nella finestra di scorrimento era la stessa utilizzata nella trasmissione. Il TCP utilizza il segmento come unità dati da trasmettere, mentre ragiona in termini di ottetti per quello che riguarda il meccanismo di ritrasmissione. Questo comporta una complicazione nella gestione delle conferme di ricezione (acknowledgement).

A causa dell'asimmetria suddetta, la ritrasmissione in caso di mancata ricezione non avviene per segmenti, ma a livello di ottetti. Questo vuol dire che un segmento può contenere contemporaneamente sia nuovi dati sia una parte dei dati persi in precedenza. Ovviamente a queste condizioni ha poco senso numerare semplicemente i segmenti e usare questo identificativo nelle conferme di ricezione. Né è pensabile di usare i datagrammi IP a tale scopo, dato che questi sono generalmente di lunghezza fissa mentre i vari segmenti TCP sono di lunghezza variabile. Ne consegue che l'unico modo per gestire le conferme è quello di ragionare in termini di cursore all'interno del flusso di dati. Come dire "ho ricevuto i primi 300 caratteri della lettera che mi hai spedito".

Ecco che cosa accade: ogni segmento contiene la posizione dell'area dati del segmento TCP all'interno del flusso di dati. Tale posizione si chiama numero di sequenza (sequence number) ed è calcolata in byte. Il destinatario estrae i vari ottetti dai segmenti ricevuti e li ricompone per ricostruire il flusso dei dati, utilizzando i numeri di sequenza per riordinare i vari segmenti.

Questi possono infatti arrivare in qualunque ordine, o essere andati persi. A questo punto, chi sta ricevendo i dati, avrà ricostruito in modo completo una parte del messaggio originario e si ritroverà alcuni dati in eccesso che non sono contigui alla parte di flusso ricostruito. Ogni volta che il destinatario riceve un segmento, manda indietro nella conferma di ricezione il numero di sequenza dell'ottetto che si aspetta di ricevere per continuare la ricostruzione, cioè il valore dell'ultimo ottetto della parte contigua ricostruita più uno.

Immaginate di dover spedire una lettera a un vostro amico. Il TCP negozia con la controparte la lunghezza massima del segmento, come vedremo più avanti. Quindi inizia a riempire il primo segmento un carattere alla volta. Quando il segmento è pieno viene spedito e viene fatto partire il contatore a tempo per quel segmento. Quindi il TCP inizia a riempire il secondo segmento, che parte regolarmente, e così dicendo. Man mano che i segmenti partono arrivano dalla controparte le conferme di ricezione. Supponiamo che

a un certo punto, dopo aver spedito 450 ottetti, arrivi per due volte al mittente la conferma che il destinatario è riuscito a ricostruire il flusso fino al 300° carattere e che si aspetta il 301°. È evidente che qualcosa è andato storto e che si sono persi dei dati. Il TCP allora spedisce un segmento che contiene di nuovo dal 301° carattere in poi, diciamo fino al 400°. Dato che i caratteri dal 370° al 450° erano comunque arrivati regolarmente, il successivo messaggio di conferma richiederà direttamente il 451° carattere, e non il 401°.

L’implementazione.

Benché il TCP presenti all’utente una visione continua dei dati, detta flusso, l’unità di trasferimento dei dati del TCP è il segmento. Un segmento è formato come al solito da una intestazione e da un’area dati. Al contrario del datagramma IP, il segmento ha dimensioni variabili nel tempo, cioè i vari segmenti spediti a fronte di uno stesso flusso possono avere lunghezze differenti. I segmenti sono utilizzati dal TCP per aprire e chiudere una connessione, trasferire dati, spedire conferme di ricezione e modificare la finestra di spedizione, quel meccanismo che garantisce un utilizzo ottimale della rete, come spiegato in precedenza. Due caratteristiche peculiari del TCP sono che lo stesso segmento può portare contemporaneamente sia dati veri e propri sia dati di controllo, e che le informazioni di controllo possono riferirsi sia allo stesso flusso dell’area dati, sia al flusso opposto (piggybacking).

L’intestazione

Innanzitutto abbiamo i numeri di porta del mittente e del destinatario, esattamente come nell’UDP. Come già nell’UDP, infatti, gli indirizzi IP delle due controparti sono contenuti nell’intestazione del datagramma IP. Al contrario di quanto avveniva nell’UDP, tuttavia, la conoscenza da parte del TCP degli indirizzi IP non rompe il paradigma che vuole un certo isolamento fra le responsabilità dei vari livelli dello stack. Il TCP infatti, architetturalmente, ragiona in termini di connessioni, e queste comprendono sia l’informazione relativa alle porte, sia quella relativa agli indirizzi IP. Anzi, ogni qual volta l’IP consegna un segmento al TCP, gli passa anche gli indirizzi IP contenuti nell’intestazione del datagramma.

Anche nel caso del segmento TCP la verifica della correttezza dell’intestazione da parte del destinatario viene effettuata utilizzando un meccanismo di somma di controllo con pseudointestazione. All’interno dell’intestazione TCP, infatti, esiste un campo chiamato somma di controllo (checksum). Il TCP imposta inizialmente tale campo di 16 bit a zero. Costruisce quindi una psedointestazione che contiene gli indirizzi IP del mittente e del destinatario, il numero di protocollo del sottosistema di trasmissione (nel caso del TCP basato su IP è sei) e la lunghezza del segmento TCP compresa l’intestazione. A questo punto appende alla pseudo intestazione il segmento IP e aggiunge alla fine dello stesso tanti zeri quanti ne servono per far sì che il blocco risultante sia un multiplo di parole da 16 bit (padding). Divide quindi il blocco in parole da 16 bit e ne calcola la somma a complemento uno. Il risultato viene quindi salvato nel campo apposito dell’intestazione e sia la pseudointestazione sia i bit aggiunti in fondo vengono rimossi prima di spedire il segmento. Il destinatario ovviamente effettuerà un calcolo analogo per verificare che il valore di controllo così ottenuto corrisponda con quello arrivato nell’intestazione del segmento.

Nell’intestazione ci sono tre campi calcolati in ottetti. Il primo è il numero di sequenza (sequence number), che rappresenta la posizione dell’area dati del segmento TCP all’interno del flusso di dati. Il secondo è il numero di conferma (acknowledgement number), ovverosia il numero di sequenza dell’ottetto che il mittente si aspetta di ricevere per continuare la ricostruzione. Da notare che tale valore corrisponde al flusso opposto rispetto a quello in cui viaggia il segmento che lo contiene. Il terzo campo è il puntatore ai dati "urgenti". Come detto prima, è possibile che il TCP debba spedire dei dati urgenti che vanno elaborati indipendentemente dal flusso normale di dati, e con priorità rispetto a quest’ultimo. In questo caso il segmento contiene un segnalatore (flag) che informa il destinatario della presenza d’informazioni urgenti nell’area dati. I dati urgenti sono posizionati all’inizio dell’area dati, e il puntatore in questione indica dove tali dati finiscono e dove ricominciano i dati normali, se ce ne sono.

I segnalatori

Separati da un’area riservata per usi futuri c’è il campo che contiene la posizione dell’area dati nel segmento e un blocco di sei segnalatori. Il primo, misurato in parole da 32 bit, indica di fatto la lunghezza dell’intestazione del segmento in tale unità di misura. questo campo è necessario in quanto in fondo all’intestazione esiste una zona riservata a eventuali opzioni che rende la lunghezza dell’intestazione non fissata a priori. Il secondo campo contiene invece sei indicatori. Data infatti nel segmento la presenza contemporanea, almeno in potenza, sia di dati di controllo sia di dati applicativi normali e urgenti, è necessario utilizzare dei segnalatori per informare il destinatario su cosa effettivamente contiene il segmento. Tutti i segnalatori sono attivi se impostati a uno, inattivi altrimenti. Il primo segnalatore indica se l’area dati contiene dati urgenti. Il secondo indica la presenza nel segmento di una conferma di ricezione valida. Dato infatti che il campo corrispondente esiste sempre e comunque nell’intestazione, se il segmento non trasporta alcuna conferma di ricezione è necessario informare in qualche modo il destinatario che tale campo va ignorato. Il terzo bit è posto a uno quando si vuole forzare la trasmissione dei dati all’utente finale indipendentemente dal fatto che il buffer di ricezione sia o meno completamente riempito. Il quarto segnalatore serve per interrompere immediatamente la connessione (reset). Tale evento avviene solo in situazioni eccezionali e causa l’interruzione immediata delle trasmissioni da ambo le parti e il rilascio del contenuto dei buffer di ricezione. Il quinto bit è detto di sincronizzazione, ed è utilizzato durante la fase iniziale di negoziazione della connessione, detta in gergo handshake. In pratica, i segmenti scambiati quando questo bit è impostato a uno servono a sincronizzare i numeri di sequenza delle due controparti prima d’iniziare la trasmissione vera e propria dei dati. L’ultimo bit serve a informare il destinatario che il mittente intende terminare in modo pulito la connessione e che non ha più dati da spedire. All’apertura e alla chiusura della connessione il TCP utilizza un algoritmo chiamato saluto a tre vie (three-way handshake) che garantisce la corretta sincronizzazione delle due operazioni.

L’ultimo campo fisso è quello relativo alla soglia di capacità del mittente (window advertisement) che contiene il numero di ulteriori ottetti che esso è in grado di ricevere. A questo punto è di nuovo importante ricordare il concetto di piggybacking, a cui già si è accennato. Ovverosia, ogni segmento può portare contemporaneamente informazioni in cui una controparte è vista sia come chi spedisce i dati contenuti nel segmento, cioè come mittente, sia come chi ha ricevuto o deve ricevere dati dall’altro capo della connessione, cioè come destinatario. Quando noi parliamo di mittente, per evitare confusione, ci riferiamo sempre al mittente del segmento di cui stiamo parlando. È importante comunque tenere sempre presente che alcuni dati del segmento hanno senso solo se si considera il mittente quale destinatario di dati precedenti o ancora da venire.

In fondo all’intestazione c’è un’area opzionale che può essere utilizzata a vari scopi. In genere essa contiene opzioni che permettono alle due controparti di negoziare alcuni aspetti della comunicazione. Un esempio è il calcolo della lunghezza ottimale del segmento.

L’implementazione del protocollo TCP

Abbiamo visto che tutto il meccanismo funziona ed è affidabile grazie alle conferme di ricezione e alla ritrasmissione dei pacchetti probabilmente andati perduti. Ma come fa a sapere il mittente che un pacchetto è andato effettivamente perduto? Ovviamente perché non è arrivata la conferma di ricezione, direte voi. Va bene, ma quanto devo aspettare tale conferma prima di assumere che sia necessaria una ritrasmissione? E qui son dolori. Se aspetto troppo rischio di rallentare la comunicazione in modo inaccettabile. Se aspetto troppo poco rischio di ritrasmettere inutilmente troppi segmenti, magari semplicemente un po’ in ritardo. Tutto il sistema si basa sul calcolo del tempo di attesa massimo, o timeout. Il TCP calcola il timeout sulla base del tempo intercorso fra la spedizione di un segmento e l’arrivo della conferma corrispondente. Sembra facile, ma non è così. Vediamo rapidamente i punti chiave del discorso.

A questo punto il timeout viene calcolato moltiplicando l’RTT per un valore maggiore di uno. Se il valore di beta è troppo vicino a uno la perdita di un pacchetto viene immediatamente rilevata, ma si rischia di ritrasmettere più pacchetti del necessario. Se viceversa beta è troppo alto si rischia di aspettare troppo a lungo prima di ritrasmettere un pacchetto perso, abbassando così le prestazioni della connessione. In genere si raccomanda per beta un valore di due. La scelta di alfa e di beta sembra dunque essere critica, ma i problemi non sono ancora finiti. Infatti, se un segmento è trasmesso due volte, quando arriva la conferma di ricezione, a chi si riferisce? Al pacchetto originale o a quello ritrasmesso? Se usiamo il primo pacchetto per il calcolo dell’RTS rischiamo di far crescere esponenzialmente il valore di timeout. Infatti un pacchetto è ritrasmesso quando scade il timeout precedente. Di conseguenza il nuovo RTS è ovviamente più grande del vecchio timeout. Se viene perso un nuovo pacchetto l’RTS cresce ancora, e così via. Se usiamo il pacchetto ritrasmesso abbiamo il problema opposto, cioè il timeout rischia di ridursi sempre di più, o almeno si è dimostrato sperimentalmente che si stabilizza su valori alquanto bassi. Supponiamo infatti di avere un ritardo in rete: la conferma di ricezione arriva conseguentemente in ritardo. Nel frattempo il mittente ha rispedito il pacchetto che credeva perso. Appena arriva la conferma questa è associata al segmento ritrasmesso generando così un RTS molto piccolo. Il timeout si riduce, aumentando il rischio di considerare persi pacchetti la cui conferma di ricezione arriva in ritardo, e così via.

P. Karn propose nel 1987 d’ignorare i pacchetti ritrasmessi nel calcolo del timeout. Questo evitava il problema suddetto, ma ne creava un altro. Se un pacchetto è ritrasmesso perché si è avuto un repentino calo di prestazioni della rete, il timeout rimarrà sempre troppo basso, in quanto il mittente continuerà a ritrasmettere pacchetti le cui conferme arrivano in ritardo rispetto al timeout calcolato prima del calo di prestazioni. Dato che tali conferme vengono regolarmente ignorate per il calcolo dell’RTT, il timeout non viene più aggiornato almeno fintanto che la rete non torna normale, cosa per giunta complicata dal sovraccarico dovuto all’inutile ritrasmissione dei pacchetti. La soluzione consiste nell’aumentare il timeout precedente a una ritrasmissione di un fattore arbitrario, diciamo gamma, fino a un limite massimo ragionevole calcolato sulla base dei possibili cammini all’interno della rete (riquadro 1). In genere gamma non è minore di due.

Questa tecnica è detta di backoff.