TCP e UDP: il livello di trasporto
Dalle porte e dai socket al confronto tra TCP e UDP, fino al laboratorio con Netcat e Wireshark.
1. Dal dispositivo all’applicazione
Su un computer possono funzionare contemporaneamente browser, posta, chat e client DNS. Condividono la rete, ma ciascuno deve ricevere i propri dati. L’indirizzo IP individua un’interfaccia di rete: da solo non identifica l’applicazione destinataria.
Il livello di trasporto permette la comunicazione tra applicazioni su host diversi, usando anche le porte. È il livello 4 del modello OSI. Nel modello TCP/IP si trova tra Applicazione e Internet: TCP e UDP utilizzano IP per raggiungere la destinazione.
| TCP/IP | Corrispondenza OSI | Ruolo |
|---|---|---|
| Applicazione | 7–6–5 | Servizi e regole dello scambio applicativo |
| Trasporto | 4 | TCP o UDP: comunicazione tra applicazioni |
| Internet | 3 | IP: indirizzamento e inoltro tra reti |
| Accesso alla rete | 2–1 | Frame, collegamenti e segnali |
Nell’incapsulamento, ai dati applicativi si aggiunge l’header TCP o UDP; il risultato diventa il contenuto di un pacchetto IP, poi di un frame sul collegamento.
2. Porte, porte effimere e socket
Una porta è un numero a 16 bit, da 0 a 65535; la porta 0 è riservata e non è una normale porta di servizio. Le porte consentono al sistema operativo di distinguere gli endpoint delle comunicazioni. Non sono connettori fisici.
Un servizio Web HTTP su TCP può ascoltare sulla porta 80; SSH usa normalmente TCP 22, DNS usa sia UDP sia TCP 53. Sono associazioni convenzionali: la sola porta non prova quale applicazione stia realmente comunicando.
Il client utilizza normalmente una porta effimera, scelta temporaneamente dal sistema operativo. Il suo intervallo dipende dal sistema e dalla configurazione. In questo esempio 49152 è una possibile porta client, non un valore obbligatorio.
Richiesta TCP: 192.168.1.10:49152 → 192.168.1.50:80
Risposta TCP: 192.168.1.50:80 → 192.168.1.10:49152
Un socket è un endpoint software. In una rete IP lo descriviamo mediante protocollo di trasporto, indirizzo IP e porta. Una connessione TCP è identificata dalla coppia di endpoint: IP e porta locali, IP e porta remoti. Questo permette a molti client di collegarsi allo stesso servizio.
3. TCP: connessione e flusso affidabile
TCP — Transmission Control Protocol offre un flusso di byte affidabile e ordinato. Prima dello scambio normale dei dati, le due estremità stabiliscono una connessione logica. Non viene creato un cavo: i sistemi mantengono uno stato con numeri di sequenza, conferme e dati ancora da trasmettere o ritrasmettere.
Affidabile non significa che la rete non possa guastarsi. TCP recupera molte perdite mediante ritrasmissioni; se non riesce a proseguire, la comunicazione può terminare con un errore. Una conferma TCP indica ricezione da parte del trasporto remoto, non che l’applicazione abbia già elaborato o salvato i dati.
Il Three-Way Handshake
- SYN: il client propone il proprio numero di sequenza iniziale.
- SYN, ACK: il server propone il suo e conferma quello del client.
- ACK: il client conferma quello del server.
Lo schema mostra l’apertura ordinaria di una connessione TCP. Il terzo segmento può già trasportare dati; esistono inoltre estensioni specifiche. Non occorre aspettarsi sempre tre righe prive di payload in ogni cattura reale.
4. Sequence Number e ACK: contare i byte
TCP numera i byte, non i messaggi. Il campo Sequence Number indica il numero del primo byte di dati del segmento. Ogni direzione ha il proprio spazio di sequenza.
Quando il flag ACK è impostato, l’Acknowledgment Number indica il prossimo numero di sequenza atteso: è una conferma cumulativa dei byte precedenti ricevuti in ordine.
Esempio con numeri relativi:
Seq = 1, dati = 12 byte → byte da 1 a 12
Risposta: Ack = 13 → attendo il byte 13
Le sequenze iniziali reali non devono partire da 1. Wireshark mostra normalmente numeri relativi per facilitarne la lettura. Anche SYN e FIN consumano ciascuno un numero di sequenza; un ACK senza dati, SYN o FIN non ne consuma.
Perdite, riordino e ritrasmissione
Se i dati arrivano fuori ordine, TCP può conservarli in attesa dei byte mancanti. Timer e informazioni dalle conferme aiutano il mittente a rilevare perdite e ritrasmettere. Non esiste l’obbligo di un ACK separato per ogni segmento: sono possibili conferme ritardate o incluse in segmenti che trasportano anche dati.
In Wireshark, TCP Retransmission, Duplicate ACK e Out-Of-Order
sono indicazioni dell’analizzatore da interpretare nel contesto della cattura, non ulteriori flag
dell’header TCP.
5. Stream, finestre e congestione
Se l’applicazione scrive CIAO, poi COME, poi STAI, TCP
trasporta il flusso CIAOCOMESTAI. Non conserva i confini di quelle tre scritture: una
send() non corrisponde necessariamente a un segmento o a una recv().
Il protocollo applicativo deve riconoscere i messaggi con lunghezze, delimitatori o header propri. Per esempio, può stabilire che ogni messaggio termini con un carattere di fine riga.
- Controllo del flusso: la finestra annunciata dal ricevitore comunica quanto spazio è disponibile per altri dati; protegge il ricevitore da un mittente troppo rapido.
- Controllo della congestione: il mittente adatta la quantità di dati in volo alle condizioni della rete. Non coincide con la finestra annunciata nell’header.
6. Header, flag e chiusura TCP
| Campo | Che cosa osservare |
|---|---|
| Source / Destination Port | Endpoint sorgente e destinazione |
| Sequence / Acknowledgment Number | Posizione nel flusso e conferma cumulativa |
| Header Length | Dimensione dell’header: da 20 a 60 byte |
| Flags | Bit di controllo, anche contemporanei |
| Window | Finestra annunciata dal ricevitore; considerare l’eventuale Window Scale |
| Checksum | Controllo di integrità; non è cifratura né autenticazione |
| Flag | Significato |
|---|---|
| SYN | Sincronizzazione dei numeri iniziali |
| ACK | Il campo Acknowledgment Number è valido |
| FIN | Il mittente non invierà altri dati in questa direzione |
| RST | Interruzione/reset, per esempio in risposta a una connessione rifiutata |
| PSH | Richiesta di non trattenere inutilmente i dati prima della consegna all’applicazione; non delimita un messaggio |
[PSH, ACK] indica entrambi i flag impostati. Nella cattura può accompagnare
dati, ma PSH non è il campo che misura la presenza o la lunghezza del payload:
controllare tcp.len. Anche un segmento senza PSH può trasportare dati.
Una chiusura ordinata possibile
Client → Server: FIN, ACK
Server → Client: ACK
Server → Client: FIN, ACK
Client → Server: ACK
TCP è full-duplex: le due direzioni si chiudono indipendentemente. Le conferme possono essere combinate e non ogni cattura mostra esattamente quattro segmenti. Un RST indica una chiusura diversa da questo esempio ordinato.
7. UDP: datagrammi senza handshake
UDP — User Datagram Protocol è connectionless: non apre una connessione con un handshake del trasporto. L’applicazione può inviare subito un datagramma.
Tre invii di messaggi UNO, DUE e TRE generano tre datagrammi:
UDP conserva i confini dei messaggi consegnati. Non garantisce però consegna, ordine o assenza di
duplicati e non ritrasmette automaticamente i dati persi.
L’header UDP è di 8 byte: porta sorgente, porta destinazione, lunghezza (header più dati) e checksum. Non contiene i campi Seq/Ack o i flag TCP.
Una risposta applicativa “ricevuto” può essere inviata su UDP, ma non diventa un ACK del protocollo
UDP. Eventuali conferme, riordino e recupero delle perdite devono essere realizzati dai protocolli
che lo utilizzano. Anche l’uso di connect() su un socket UDP non introduce un handshake
UDP.
8. Scegliere il trasporto
| Caratteristica | TCP | UDP |
|---|---|---|
| Servizio | Flusso di byte | Datagrammi con confini conservati |
| Apertura ordinaria | Handshake e stato di connessione | Nessun handshake UDP |
| Consegna e ordine | Recupero perdite e consegna ordinata, oppure fallimento della connessione | Nessuna garanzia offerta da UDP |
| Conferme e ritrasmissioni | Gestite da TCP | Non fornite da UDP |
| Flusso e congestione | Meccanismi TCP | Non forniti da UDP stesso |
| Header | 20–60 byte | 8 byte |
HTTP/1.1, HTTP/2 e SSH usano TCP. DNS può usare UDP e TCP; DHCP e NTP usano UDP. HTTP/3 usa QUIC, un protocollo basato su UDP che offre, tra le altre funzioni, flussi affidabili. Non tutto il traffico HTTPS usa quindi TCP.
9. Preparare il laboratorio: Netcat e loopback
Servono una macchina o VM Linux con Netcat e Wireshark, due terminali e la possibilità di catturare
sull’interfaccia lo. Client e server girano sulla stessa macchina:
127.0.0.1 indica il loopback locale, anche dentro una VM. Questo traffico non esce
sulla scheda Ethernet.
Netcat è un’applicazione, non un protocollo. Legge e scrive dati attraverso TCP o
UDP; il kernel gestisce il trasporto. Wireshark osserva i pacchetti. Avviare la cattura su
lo prima di collegare il client.
Controllare quale Netcat è installato
nc -h
La sintassi cambia tra implementazioni. Gli esempi TCP usano la sintassi OpenBSD Netcat; per UDP riportiamo il comando della schermata. Le opzioni
-l e -u significano rispettivamente ascolto e UDP. Nella versione
traditional i comandi di ascolto possono essere nc -l -p 5000 e
nc -u -l -p 6000: seguire l’help della propria versione, senza mescolare le sintassi.
In Wireshark usare i seguenti come filtri di visualizzazione, nella barra sopra i pacchetti, non come filtri di cattura.
tcp.port == 5000
udp.port == 6000
tcp.port == 5000 nella barra del filtro
di visualizzazione e premere Invio. Sono mostrati i pacchetti TCP con porta sorgente o
destinazione 5000; prima del collegamento del client la lista può essere vuota.10. Esperimento TCP: prima la connessione, poi i dati
- Avviare la cattura su
loe impostaretcp.port == 5000. - Nel terminale server avviare l’ascolto:
nc -l 127.0.0.1 5000
Nel secondo terminale collegare il client:
nc 127.0.0.1 5000
Prima di digitare: individuare SYN, SYN/ACK e ACK. Annotare la porta effimera del client, la porta server 5000, Seq e Ack. Lo stack TCP del kernel ha aperto la connessione richiesta da Netcat.
127.0.0.1:5000. A destra Wireshark mostra SYN → SYN/ACK →
ACK, prima dell’invio del testo.La schermata usa il comando di ascolto nc -l -p 5000, una delle sintassi indicate sopra.
Nella cattura la porta effimera del client è 40528: nella propria prova può essere
diversa. Entrambi gli indirizzi sono 127.0.0.1; le porte distinguono i due endpoint.
Nel client digitare Ciao e premere Invio. Il testo compare sul server. Rispondere dal
terminale server e osservare l’inversione di porte sorgente e destinazione.
Ciao compare sul server. La cattura
mostra il segmento con i dati e la successiva conferma TCP.Espandere TCP nel dettaglio del pacchetto e cercare il payload. Nella schermata Ciao
contiene 4 byte ASCII; il fine riga aggiunge un byte, per un totale di 5 byte. I
valori esadecimali sono 43 69 61 6f 0a: 0a rappresenta il fine riga.
Il pacchetto 6 mostra [PSH, ACK], Seq = 1 e Len = 5. Nel
pacchetto 7 il server risponde con Ack = 6: attende il byte successivo ai cinque
ricevuti. Sono numeri di sequenza relativi. La lunghezza del frame visualizzata nella colonna
Length non coincide con i soli dati TCP: per il payload controllare tcp.len.
In altre prove segmentazione e buffering possono variare.
tcp.port == 5000 && tcp.len > 0
Usare Follow → TCP Stream per ricostruire il dialogo. Non aspettarsi necessariamente PSH o un ACK separato per ogni riga. Terminare i processi con Ctrl+C; se si analizza la chiusura, distinguere FIN e RST realmente osservati, senza imporre lo schema teorico.
11. Esperimento UDP: osservare i datagrammi
Terminare l’esperimento precedente, avviare una nuova cattura su lo e usare
udp.port == 6000.
Terminale server, con la sintassi usata nella schermata:
nc -u -l 127.0.0.1 -p 6000
L’opzione -p 6000 specifica la porta locale di ascolto. Se la propria versione OpenBSD non accetta questa combinazione, usare nc -u -l 127.0.0.1 6000, come indicato dal relativo help.
Terminale client:
nc -u 127.0.0.1 6000
Digitare Ciao Server! e premere Invio, come nella schermata. Il testo contiene 12 byte ASCII; con il fine riga il payload è di 13 byte. Il campo UDP Length vale quindi 21 byte: 8 di header più 13 di dati. Il riepilogo Len=13 nella colonna Info indica invece i soli dati.
Ciao Server! al server UDP sulla porta 6000. Wireshark mostra il datagramma e il payload: UDP non esegue la sequenza SYN, SYN/ACK, ACK.Nella cattura la porta effimera del client è 45664; nella propria prova può cambiare. Per controllare tutto il traffico della porta, anche senza limitarlo a UDP, si può usare udp.port == 6000 || tcp.port == 6000: il solo filtro UDP nasconderebbe eventuali pacchetti TCP.
Non compare un handshake UDP né un ACK UDP. Per osservare le due direzioni, dopo il primo messaggio rispondere dal server: quello è un nuovo datagramma con dati applicativi, non una conferma automatica di UDP.
Se non compare traffico
- Verificare che entrambi i terminali siano nella stessa VM e che la cattura sia su
lo. - Controllare protocollo, porta, processo in ascolto e sintassi della variante Netcat.
- Premere Invio: il terminale può conservare il testo finché la riga non è completa.
- Se Wireshark non elenca le interfacce catturabili, verificare con il docente i permessi di cattura.