PMTUD e TCP MSS

Topologia di massima

Due filiali interconnesse mediante un tunnel GRE/IPSEC instaurato sfruttando le rispettive linee ADSL. In particolare, sul sito A sono presenti diversi client che hanno necessità di “dialogare” con un server Web posto nel sito B.

Problema

I client accedono al server Web remoto con estrema lentezza e molte delle richieste effettuate vanno in timeout. Nella fattispecie, trattasi di un problema legato alla MTU (Maximum Transmission Unit) configurata sulle interfacce dei router delle 2 filiali, che provoca la suddetta sintomatologia.

Un po’ di teoria

Ma cos’è l’MTU? Essa, molto semplicemente, definisce la dimensione massima (in byte) di un pacchetto (o di un frame) che può attraversare una determinata interfaccia di rete. Ad esempio, nel caso del protocollo IP (layer 3) parliamo generalmente di 1500 byte, mentre nel caso del protocollo Ethernet (layer 2) la MTU è pari a 1526 byte (1500 byte “ereditati” dal protocollo IP + 22 byte di instestazione Ethernet e 4 byte di CRC). Quest’ultima è sicuramente la più rognosa, in quanto molto spesso gli switch sono unmanaged e quindi non è possibile accorgersi immediatamente dei cosiddetti frame giant, che vegnono quindi scartati “silenziosamente” provocando una comunicazione “a singhiozzo” (vedi questo post per ulteriori dettagli).

Per quanto riguarda invece la MTU IP, si avranno sicuramente dei problemi nel caso in cui:

1) i valori configurati sulle interfacce del router A e del router B differiscono tra di loro (in gergo parliamo di MTU mismatch);

2) lungo il cammino tra router A e il router B esiste un segmento la cui MTU è inferiore rispetto a quella configurata sui 2 router.

Nel primo caso possiamo correre ai ripari molto velocemente, configurando un valore di MTU identico sulle interfacce dei router delle 2 filiali. Ad esempio, possiamo definire la MTU di una data interfaccia utilizzando il comando:

Router(config-if)# ip mtu <valore in byte>

Nel secondo caso, invece, occorre fare un po’ di diagnostica ed eventualmente utilizzare delle configurazioni ad hoc.

In entrambi i casi i pacchetti che superano la MTU più bassa verranno “frammentati” e ricostruiti in fase di ricezione. Ovviamente tale operazione, oltre a causare un overhead sui router coinvolti, provocherà dei seri problemi a livello 4 (TCP) e superiori, inficiando in modo notevole l’accesso al servizio da parte degli utenti.

PMTUD

Per evitare quindi che si verifichi un’eccessiva frammentazione è stato messo a punto un meccanismo tale per cui un router riuscirà ad accorgersi automaticamente della presenza di un valore di MTU inferiore rispetto a quello configurato sulla propria interfaccia, riducendo di conseguenza la dimensione dei pacchetti che intende inoltrare. Tale meccanismo prende il nome di Path MTU Discovery, abbreviato in PMTUD. Più in dettaglio, essa si basa sull’invio/ricezione di messaggi ICMP unreachable type 3 code 4 ( vedi qui per ulteriori dettagli): se la MTU dei pacchetti ricevuti da un router supera la dimensione massima definita sulla propria interfaccia in ricezione, esso procederà con l’inoltro del suddetto messaggio verso il router mittente. In tal modo, quest’ultimo si accorgerà di quanto sta avvenendo e ridurrà di conseguenza la MTU in modo da riuscire ad “attraversare” il router interessato.

PMTUDOra, occorre precisare che non è tutto oro ciò che luccica, nel senso che molto spesso i pacchetti ICMP unreachable vengono disabilitati sia in TX che in RX (in questo caso si parla di PMTUD blackhole). Ad esempio, nel caso dei dispositivi di casa Cisco, essi sono disabilitati di default:

Router#sh ip int dia0 | i ICMP
  ICMP redirects are never sent
  ICMP unreachables are never sent
  ICMP mask replies are never sent

Il perchè di tale configurazione è presto detto: per loro stessa natura, i messaggi ICMP consentono di ottenere informazioni “sensibili” sulla rete target e possono anche essere utilizzati per generare attacchi di tipo DoS/DDoS. Infatti, se un utente malevolo facesse in modo di “sollecitare” la generazione dei messaggi ICMP unreachable da parte del router oggetto dell’attacco, riuscirebbe certamente a sovraccaricarlo, poichè la generazione del suddetto tipo di messagistica avviene a livello di CPU. Come workaround è comunque possibile settare un rate limit specifico, ad esempio:

Router(config)# ip icmp rate-limit unreachable df 500

dove 500 rappresenta il numero di millisecondi che deve intercorrere tra la generazione di un messaggio ICMP unreachable e quello successivo.

A titolo di cronaca, per abilitare i suddetti messaggi su una data interfaccia è sufficiente digitare il comando:

Router(config-if)# ip unreachable

Identificare il valore di MTU corretto: metodo trial and error

Occorre precisare che esiste un modo empirico per determinare la dimensione della MTU più piccola presente lungo il percorso tra il router A ed il router B. Esso si basa sull’utilizzo del comando ping dotato delle flag -f (che imposta a 1 il bit do not fragment nell’header IP) e -l (che imposta la dimensione del solo payload). Se ad esempio la MTU configurata sulla scheda di rete del nostro PC (con Windows 7 a bordo) fosse pari a 1500 byte, potremmo utilizzare il comando:

C:\Users\pippo> ping 192.168.1.1 -f -l 1472

dove 1472 è il massimo payload definibile senza che vi sia frammentazione, poichè ad esso verranno sommati i 20 byte di intestazione IP e gli 8 byte di instestazione ICMP (per un totale di 1500 byte). Utilizzando un payload di 1473 byte, la nostra scheda ci indicherà che abbiamo superato la MTU attraverso il seguente output:

C:\Users\pippo>ping 192.168.1.1 -l 1473 -f

Esecuzione di Ping 192.168.1.1 con 1473 byte di dati:
E' necessario frammentare il pacchetto ma DF è attivo.
E' necessario frammentare il pacchetto ma DF è attivo.
E' necessario frammentare il pacchetto ma DF è attivo.
E' necessario frammentare il pacchetto ma DF è attivo.

Tale metodo può essere utilizzato per identificare la MTU di interesse, abbassando di volta in volta la dimensione del payload fino a quando al posto del suddetto messaggio verranno visualizzati dei semplici ICMP echo reply.

Una piccola nota a margine: nel caso in cui si volesse utilizzare questa metodologia direttamente dalla CLI del router Cisco, è possibile utilizzare il seguente comando:

ping 192.168.1.1 source fa0/0 df-bit size 1500

dove 1500, in questo caso, rappresenta la dimensione totale del messaggio ICMP echo request (e non del solo payload come avveniva nel caso di Windows 7).

TCP MSS

L’acronimo MSS sta per Maximum Segment Size e rappresenta la dimensione massima (in byte) che può avere il payload (e solo il payload) di un segmento TCP. Il valore di default è 1460, ovvero 1500 byte di MTU meno i 20 byte di instestazione TCP ed i 20 byte di intestazione IP. Nel caso in cui la MTU più piccola relativa al percorso tra A a B fosse inferiore a quella di default, è possibile “forzare” il valore di MSS (in gergo parliamo di MSS clamping). Ad esempio, per i router Cisco potremo utilizzare il comando:

Router(config-if)# ip tcp adjust-mss <byte>

dove i byte da utilizzare sono dati dalla MTU più piccola meno 40 byte.

Un caso pratico (e molto diffuso tra gli end user) in cui l’MSS clamping torna davvero utile riguarda il protocollo PPPoE, che usa una MTU pari a 1492 byte (a differenza del PPPoA la cui MTU è quella classica, ovvero 1500 byte). In tal caso si può procedere con questa configurazione sull’interfaccia dia0:

Router(config-if)# ip mtu 1492
Router(config-if)# ip tcp adjust-mss 1452

Spero di aver fatto un minimo di chiarezza sul concetto di MTU e su quanto esso sia importante nell’ambito della comunicazione client/server basata sul protocollo TCP e superiori.

Alla prossima.

PMTUD e TCP MSSultima modifica: 2016-02-03T19:51:00+01:00da nazarenolatella
Reposta per primo quest’articolo

Lascia un commento