TCP: handshake a tre vie e chiusura della connessione

// obiettivi di apprendimento
Descrivere passo per passo il three-way handshake TCP e spiegare il ruolo di SYN, SYN-ACK e ACK
Comprendere il concetto di ISN (Initial Sequence Number) e perché viene scelto casualmente
Analizzare il four-way handshake di chiusura e la finalità del periodo TIME_WAIT
Distinguere tra chiusura graceful (FIN) e chiusura anomala (RST)
📄
Slides
Diagrammi di stato e timeline delle connessioni
Scarica →

Perché TCP richiede un handshake?

TCP è un protocollo connection-oriented: prima che un singolo byte di dati venga scambiato, i due host devono concordare i parametri della connessione. Questo scambio preliminare serve a:

  • Sincronizzare i numeri di sequenza iniziali (ISN) di entrambi i lati
  • Verificare che entrambi gli host siano raggiungibili e pronti
  • Negoziare le opzioni TCP (MSS, Window Scale, SACK, Timestamps)
  • Allocare i buffer di ricezione e inizializzare le variabili di stato
// definizione formale
Il three-way handshake TCP è la procedura in tre passi attraverso cui due endpoint TCP stabiliscono una connessione full-duplex, sincronizzando i reciproci numeri di sequenza iniziali (ISN) prima dello scambio di dati (RFC 9293, §3.4).

Three-Way Handshake — Apertura della connessione

Client                          Server
  |                               |
  |--- SYN (seq=x) -------------->|   Client: SYN_SENT
  |                               |   Server: SYN_RECEIVED
  |<-- SYN-ACK (seq=y, ack=x+1) --|
  |                               |
  |--- ACK (ack=y+1) ------------>|   Entrambi: ESTABLISHED
  |                               |
         [ dati possono fluire ]
PassoSegmentoFlagSeq/AckSignificato
1Client → ServerSYNseq=x (ISN client)Il client vuole aprire una connessione e comunica il suo ISN
2Server → ClientSYN+ACKseq=y (ISN server), ack=x+1Il server accetta e comunica il suo ISN; riscontra il SYN del client
3Client → ServerACKack=y+1Il client riscontra il SYN del server — connessione stabilita
// nota — SYN occupa un numero di sequenza

Il segmento SYN non trasporta payload ma occupa 1 numero di sequenza (come se fosse 1 byte di dati). Per questo l’ACK del passo 3 vale y+1 anche se il SYN-ACK del passo 2 aveva payload zero. Lo stesso vale per FIN.

ISN — Initial Sequence Number

L’ISN non parte da 0: viene scelto pseudocasualmente da ciascun host al momento dell’apertura. I motivi sono fondamentalmente due:

  • Sicurezza: un ISN prevedibile permetterebbe a un attaccante di forgiare segmenti TCP validi (IP spoofing / sequence prediction attack, CVE storico)
  • Distinzione da connessioni precedenti: evita che segmenti ritardati di una vecchia connessione sulle stesse porte vengano interpretati come appartenenti alla connessione corrente

Nelle implementazioni moderne, l’ISN è generato con una funzione che tiene conto dell’IP sorgente, IP destinazione, porte e un timestamp crittograficamente randomizzato (RFC 6528).

Four-Way Handshake — Chiusura della connessione

TCP è full-duplex: ogni direzione deve essere chiusa separatamente. La chiusura avviene con un four-way handshake, detto anche half-close sequenziale.

Client (inizia la chiusura)       Server
  |                               |
  |--- FIN (seq=u) -------------->|   Client: FIN_WAIT_1
  |<-- ACK (ack=u+1) -------------|   Client: FIN_WAIT_2  /  Server: CLOSE_WAIT
  |                               |   (il server può ancora inviare dati!)
  |<-- FIN (seq=v) ---------------|   Server: LAST_ACK
  |--- ACK (ack=v+1) ------------>|   Client: TIME_WAIT → CLOSED (dopo 2×MSL)
  |                               |   Server: CLOSED
PassoSegmentoFlagStato clientSignificato
1Client → ServerFINFIN_WAIT_1Il client non ha più dati da inviare
2Server → ClientACKFIN_WAIT_2Il server riscontra il FIN; la direzione client→server è chiusa
3Server → ClientFINTIME_WAITIl server ha finito di inviare e chiude la sua direzione
4Client → ServerACKTIME_WAIT (→ CLOSED)Il client riscontra il FIN del server

TIME_WAIT — 2×MSL

// attenzione — TIME_WAIT non è un bug

Il client rimane in stato TIME_WAIT per 2×MSL (Maximum Segment Lifetime, tipicamente 30–60 s → TIME_WAIT ≈ 60–120 s). Scopo: garantire che l’ACK finale sia arrivato al server e che eventuali segmenti ritardati della vecchia connessione scadano. Solo dopo TIME_WAIT le stesse 4-tuple di porte possono essere riutilizzate.

Chiusura simultanea e RST

Esistono due varianti della chiusura:

  • Chiusura simultanea: entrambi gli host inviano FIN contemporaneamente. Ogni lato riceve un FIN e risponde con ACK — la macchina a stati gestisce questo caso simmetrico
  • RST (Reset): chiusura immediata e anomala. Nessun graceful close. Causato da: connessione a porta chiusa, crash del processo, timeout, sicurezza. Il destinatario sa che la connessione è terminata ma non può distinguere tra errore e attacco
// pericolo — RST injection

I segmenti RST possono essere forgiati da un attaccante se è in grado di indovinare il numero di sequenza (vulnerabilità storica usata da firewall stateful per terminare connessioni “indesiderate” — es. Great Firewall of China usa RST injection).

La macchina a stati TCP

Gli stati di una connessione TCP sono definiti formalmente in RFC 9293. I principali da conoscere:

StatoQuando
CLOSEDStato iniziale e finale — nessuna connessione
LISTENServer in ascolto su una porta (ha chiamato bind() + listen())
SYN_SENTClient ha inviato SYN, attende SYN-ACK
SYN_RECEIVEDServer ha ricevuto SYN e inviato SYN-ACK
ESTABLISHEDConnessione attiva — scambio dati
FIN_WAIT_1/2Lato che ha iniziato la chiusura attende ACK/FIN
CLOSE_WAITServer ha ricevuto FIN del client, ma non ha ancora chiuso il suo lato
TIME_WAITClient attende 2×MSL prima di liberare le porte
LAST_ACKServer ha inviato FIN, attende l’ACK finale
// strumenti — visualizzare gli stati

Per osservare gli stati TCP live su Linux: ss -tan oppure netstat -an | grep tcp. Nella colonna State trovi ESTABLISHED, TIME_WAIT, CLOSE_WAIT ecc. Utile per diagnosticare connessioni “bloccate” o server con troppe connessioni in CLOSE_WAIT.

📌 Riepilogo — Punti chiave
  • Il three-way handshake (SYN → SYN-ACK → ACK) sincronizza gli ISN e stabilisce la connessione in 3 scambi
  • L’ISN è scelto casualmente per motivi di sicurezza e per distinguere connessioni precedenti
  • La chiusura avviene con un four-way handshake: ogni direzione si chiude indipendentemente con FIN + ACK
  • TIME_WAIT (2×MSL) impedisce che segmenti ritardati di una connessione infestino la successiva sulle stesse porte
  • RST chiude immediatamente la connessione in modo anomalo — nessun graceful close
  • La macchina a stati TCP (LISTEN → SYN_SENT → ESTABLISHED → TIME_WAIT → CLOSED) è definita in RFC 9293

Lascia un commento