Skip to main content
  1. Concetti/

TCP Handshake

·8 mins
Alessio Barnini
Author
Alessio Barnini
Table of Contents

Mappa Globale
#

Cos'e'
#

Sequenza di pacchetti che stabilisce, mantiene e chiude una connessione TCP. Ogni pacchetto porta uno o piu' flag che indicano lo scopo del pacchetto. Leggere i flag in tcpdump e' la competenza base di un SOC analyst.

TL;DR
#

Prima dei dati → negoziazione obbligatoria in 3 pacchetti
Durante        → dati con conferma (ACK) ad ogni scambio
Chiusura       → FIN (educata) o RST (brusca)

Esempio reale visto in tcpdump durante SSH da Kali a Ubuntu:

192.168.64.200 > 192.168.64.3.22: Flags [S]    # SYN
192.168.64.3.22 > 192.168.64.200: Flags [S.]   # SYN+ACK
192.168.64.200 > 192.168.64.3.22: Flags [.]    # ACK
192.168.64.200 > 192.168.64.3.22: Flags [P.]   # PUSH dati
192.168.64.3.22 > 192.168.64.200: Flags [.]    # ACK conferma

I Flag TCP
#

FlagSimbolo tcpdumpNome completoTraduzioneSignificato operativo
SYN[S]SynchronizeSincronizzaApre la connessione — "voglio connettermi"
ACK[.]AcknowledgeConfermaConferma ricezione — "ho ricevuto"
SYN+ACK[S.]Synchronize + AcknowledgeSincronizza + ConfermaRisposta al SYN — "ok, e tu?"
PSH[P.]PushSpingiConsuma questi dati subito, non aspettare il buffer
RST[R]ResetReimpostaChiude bruscamente — porta chiusa o errore
FIN[F.]FinishFinisciChiusura elegante — "ho finito di mandare"
URG[U]UrgentUrgenteDati urgenti — raramente usato

Three-Way Handshake (3 passi) APERTURA
#

Client                        Server
  |                              |
  |  ------- [S] SYN -------->   |   "voglio connettermi"
  |                              |
  |  <------ [S.] SYN+ACK ----   |   "ok, sono pronto. tu?"
  |                              |
  |  ------- [.] ACK -------->   |   "confermato, si parte"
  |                              |
  |       CONNESSIONE APERTA     |
  |                              |
  |  ------- [P.] dati ------>   |   i dati veri iniziano qui
  |                              |
  |  <------ [.] ACK ----------  |   "ricevuto"

Il terzo pacchetto [.] e' solo ACK — lunghezza 0, nessun dato. I dati viaggiano solo dopo la connessione stabilita.

Four-Way Handshake (4 passi) CHIUSURA
#

Client                        Server
  |                              |
  |  ------- [F.] FIN+ACK --->   |   "ho finito di mandare"
  |                              |
  |  <------ [F.] FIN+ACK ----   |   "anch'io ho finito"
  |                              |
  |  ------- [.] ACK -------->   |   "confermato"
  |                              |
  |       CONNESSIONE CHIUSA     | 

Chiusura: FIN vs RST
#

Due modi per chiudere una connessione — molto diversi dal punto di vista difensivo:

CHIUSURA ELEGANTE (FIN)           CHIUSURA BRUSCA (RST)
Client         Server             Client         Server
  |                |                |                |
  | -- [F.] FIN -> |                | <-- [R] RST -- |
  | <- [.] ACK --- |                |                |
  | <- [F.] FIN -- |             connessione         |
  | -- [.] ACK --> |             tagliata            |
  |                |             immediatamente      |
  connessione      |
  chiusa           |
  correttamente

Dal punto di vista SOC:

Molti FIN   → traffico normale, sessioni che finiscono
Molti RST   → segnale sospetto:
              - port scan in corso
              - servizio che crasha
              - firewall che blocca
              - SYN flood

Port Scan — cosa vedi in tcpdump
#

Un nmap -sS (SYN scan) sulla stessa rete produce pattern riconoscibili:

PORTA APERTA (es. 22 SSH)
  Kali  --[S]-->  Ubuntu:22     SYN
  Ubuntu  --[S.]--> Kali        SYN+ACK  (il servizio risponde)
  Kali  --[R]-->  Ubuntu:22     RST      (nmap taglia prima del terzo ACK)

PORTA CHIUSA (es. 801)
  Kali  --[S]-->  Ubuntu:801    SYN
  Ubuntu  --[R.]--> Kali        RST      (nessun servizio in ascolto)

Differenza chiave: porta aperta risponde [S.], porta chiusa risponde [R.].


SYN Scan — perche' e' silenzioso
#

Il SYN scan (nmap -sS) non completa mai il handshake:

Handshake completo               SYN Scan
(connessione normale)            (nmap -sS)

[S]  -->                         [S]  -->
[S.] <--                         [S.] <--
[.]  -->   ← terzo passo         [R]  -->   ← nmap manda RST
             registrato nei log              NON registrato nei log
             del servizio                    del servizio

Risultato: auth.log e i log SSH non vedono nulla. tcpdump sul livello di rete vede tutto.

Lezione difensiva: i log applicativi non bastano — serve cattura a livello di rete.


SYN Flood — attacco DoS
#

Variante offensiva del SYN scan:

Attaccante manda migliaia di [S] verso la stessa porta
senza mai completare il handshake.

Il server tiene aperta una "half-open connection" per ognuno
in attesa del terzo [.] che non arrivera' mai.

Quando le half-open connections esauriscono la memoria:
  → nuove connessioni legittime vengono rifiutate
  → il servizio va giu'

Pattern in tcpdump che lo indica:

# Tanti SYN dallo stesso IP verso la stessa porta, nessun ACK finale
sudo tcpdump -i enp0s1 'tcp[tcpflags] & tcp-syn != 0'

ARP — il livello sotto TCP
#

Prima che TCP possa mandare il primo SYN, la macchina deve sapere il MAC address della destinazione. Questo avviene via ARP:

Kali vuole mandare SYN a Ubuntu (192.168.64.3)

PRIMA:
  Kali  -->  broadcast  "chi ha 192.168.64.3? dimmelo"   ARP Request
  Ubuntu -->  Kali  "sono io, MAC b6:56:08:90:16:03"     ARP Reply
  Kali salva in ARP cache: 192.168.64.3 = quel MAC

POI:
  Kali  -->  Ubuntu  [S] SYN                              TCP inizia

La ARP cache evita di fare questa domanda ad ogni pacchetto. Stati della cache:

REACHABLE  → comunicato di recente, MAC valido con certezza
STALE      → obsoleto — non comunichiamo da un po',
             probabilmente ancora valido ma verifichero'
             alla prossima comunicazione
FAILED     → ho provato, nessuno ha risposto (host giu' o
             non raggiungibile — come 8.8.8.8 senza gateway)

Scenario Reale — riconoscere un port scan nei log
#

Un analista SOC vede questo pattern in tcpdump:

14:30:45.000 IP 10.0.0.50 > 10.0.0.3.22:   Flags [S.]  → porta aperta
14:30:45.001 IP 10.0.0.50 > 10.0.0.3.23:   Flags [R.]  → porta chiusa
14:30:45.001 IP 10.0.0.50 > 10.0.0.3.80:   Flags [R.]  → porta chiusa
14:30:45.002 IP 10.0.0.50 > 10.0.0.3.443:  Flags [S.]  → porta aperta
14:30:45.002 IP 10.0.0.50 > 10.0.0.3.3306: Flags [R.]  → porta chiusa

Segnali di port scan:

  • stesso IP sorgente verso molte porte in rapida sequenza
  • mix di [S.] e [R.] come risposta
  • nessun [.] di completamento (SYN scan)
  • auth.log vuoto — il servizio non ha visto nulla

Azione: blocca l'IP sorgente, controlla se ha gia' stabilito connessioni, cerca nei log applicativi tracce di tentativi riusciti.


Tipi di Scan e Cosa Rivelano
#

I diversi tipi di scan nmap usano combinazioni di flag TCP diverse per ottenere informazioni senza completare il handshake. Ogni tipo rivela qualcosa di diverso.

ScanFlag inviatiRisposta porta apertaRisposta porta chiusaCosa rivela
SYN scan (-sS)SYNSYN+ACK, poi nmap manda RSTRSTPorta aperta/chiusa. Stealth: non logga nei servizi.
ACK scan (-sA)ACKRST (senza filtro)RST (senza filtro)Non rileva porte aperte - rileva se firewall e' stateful o stateless
FIN scan (-sF)FINSilenzio (RFC 793)RSTElude firewall che filtrano solo SYN. Non funziona su Windows
XMAS scan (-sX)FIN+PSH+URGSilenzioRSTCome FIN ma piu' riconoscibile. Illumina tutti i flag come un albero di Natale
NULL scan (-sN)nessun flagSilenzioRSTCome FIN ma nessun flag. Elude IDS signature-based che cercano flag specifici

ACK scan e stateful firewall: un firewall stateful tiene traccia della connection table. Un pacchetto ACK senza un corrispondente SYN precedente viene bloccato come "out of state". Un firewall stateless risponde con RST al pacchetto ACK perche' non ha memoria. Questo permette di determinare il tipo di firewall in uso.


SYN Cookies — Difesa al SYN Flood
#

Il SYN Flood esaurisce la memoria del server riempiendo la tabella delle half-open connections. La difesa classica e' i SYN Cookies: il server non alloca memoria per ogni SYN ricevuto.

Come funziona:

  1. Server riceve SYN da un client
  2. Invece di allocare una entry nella connection table, il server calcola un sequence number crittografico (cookie) basato su IP sorgente, porta, timestamp
  3. Manda SYN+ACK con quel sequence number come ISN (Initial Sequence Number)
  4. Solo quando riceve l'ACK con il sequence number+1 corretto, il server verifica il cookie e alloca la connessione

Risultato: il server non alloca memoria finche' non riceve l'ACK finale. Un attaccante che manda milioni di SYN senza mai mandare ACK non consuma memoria del server.

# Verificare se SYN Cookies e' attivo su Linux
cat /proc/sys/net/ipv4/tcp_syncookies
# 1 = attivo (default su kernel moderni)

# Abilitare permanentemente
echo "net.ipv4.tcp_syncookies = 1" >> /etc/sysctl.conf
sysctl -p

TCP Reset Attack
#

Il TCP Reset Attack inietta un pacchetto RST forgiato in una connessione TCP stabilita per interromperla bruscamente. Non richiede una posizione MITM completa: basta essere in grado di inviare pacchetti con IP spoofato.

Requisito critico: il sequence number del pacchetto RST deve essere nel range accettabile della connessione. Un attaccante che monitora il traffico puo' estrarre il sequence number attuale e forgiare un RST valido.

Usi documentati:

  • Great Firewall of China: inietta RST per interrompere connessioni verso siti censurati. Wireshark mostra RST da IP che non appartengono alla connessione.
  • Censura ISP: alcuni ISP iniettano RST per bloccare traffico peer-to-peer.
  • Attacco DoS selettivo: interrompere sessioni SSH o VPN specifiche senza bloccare tutto il traffico.

Stateful Firewall e Connection Table
#

Un firewall stateful non analizza ogni pacchetto in isolamento: mantiene una connection table con lo stato di ogni connessione TCP attiva.

stateDiagram-v2
  [*] --> LISTEN : server in ascolto
  LISTEN --> SYN_RECEIVED : riceve SYN
  SYN_RECEIVED --> ESTABLISHED : riceve ACK (handshake completo)
  ESTABLISHED --> FIN_WAIT : riceve FIN
  FIN_WAIT --> [*] : chiusura completata

  note right of SYN_RECEIVED : Firewall: crea entry nella connection table
  note right of ESTABLISHED : Firewall: aggiorna stato connessione

Perche' il firewall stateful blocca i pacchetti fuori sequenza:

  • Un ACK senza SYN precedente → no entry in connection table → bloccato
  • Un FIN su una connessione non stabilita → fuori sequenza → bloccato
  • Un RST su connessione inesistente → anomalia → bloccato (o loggato)

Questo e' il motivo per cui l'ACK scan non rileva porte aperte/chiuse su un firewall stateful: tutti i pacchetti ACK vengono bloccati indiscriminatamente perche' nessuno ha un SYN precedente registrato.

Dev parallel: Come il middleware di sessione in Express.js o Laravel: ogni request viene verificata contro la session table. Se arrivi con un cookie di sessione che non esiste nel session store, vieni rifiutato - anche se il cookie ha una struttura valida. Il firewall stateful fa la stessa cosa con i pacchetti TCP: "questa connessione esiste nella mia tabella? No? Bloccato."


Collegato a
#

  • incidents — categoria
  • tcp-udp — protocollo TCP nel contesto piu' ampio
  • syn-flood — approfondimento SYN flood e SYN cookies
  • ids-ips — IDS rileva pattern di scan (SYN/XMAS/NULL) nel traffico

Related