IPv6, crash-course

Francesco Prelz

INFN, sezione di Milano

per conto del gruppo d'interesse INFN per IPv6.

Cosa cambia, cosa resta uguale.

IPv6 vs. IPv4
  1. Per l'utente
    (che potrebbe non accorgersene)
  2. Per l'amministratore di sistema e di rete
    (che ha paure non infondate)
    • Quali differenze semantiche per IPv6?
  3. Per chi scrive o mantiene codice che usa la rete
    (che deve fare il grosso del lavoro ma non ne ha molta voglia).

IPv6 101 (1) - Indirizzi

Indirizzi IP:


IPv4:
32 bit, scritti normalmente come 4 gruppi di 8 bit, in notazione decimale:
192.84.138.10
(corrisponderebbe in esadecimale a c0.54.8a.0a)


IPv6:
128 bit, scritti normalmente come 8 gruppi di 16 bit, in notazione esadecimale (gli zeri più significativi di ciascun gruppo si possono omettere):
2001:760:4210:1:a192:b084:c138:d010

IPv6 101 (2) - Sottoreti

Sottoreti:


IPv4:
Si può utilizzare la netmask:
192.84.138.0 255.255.255.0
oppure la lunghezza del prefisso (come nella notazione CIDR):
192.84.138.0/24

IPv6:
Soltanto la lunghezza del prefisso. Gli zeri alla fine dell'indirizzo sono rappresentati da '::' (può essere utilizzato una volta sola in un indirizzo per sostituire una sequenza di zeri):
2001:760:4210:1::/64
Rete più piccola raccomandata: /64.
Ad ogni sezione INFN o centro Tier2 viene assegnata una rete /48.

IPv6 101 (3) - Famiglie di indirizzi

Classe di indirizzamentoPrefisso IPv6equivalente IPv4
Local Host::1/128127.0.0.1
Link-Localfe80::/10"Zeroconf", 169.254/16, RFC3927.
(Globally) Unique Local Addresses (RFC4193)fc00::/7Classi private (10/8, 172.16/12, 192.168/16) - nessuna speranza che possano essere unici globalmente.
Temporanei (per la privacy, RFC4941)Non distinguibili da indirizzi unicast autoconfigurati.Non disponibili.
Unicast pubblici::/00.0.0.0/0
Multicast pubbliciff00::/8224.0.0.0/4

IPv6 101 (4) - Broadcast

Broadcast vs. Multicast

L'indirizzo di broadcast IPv4, 255.255.255.255 viene tradotto in un broadcast Ethernet (FF:FF:FF:FF:FF:FF) per raggiungere tutti i nodi di una sottorete.

In IPv6 tutti gli host sono raggiungibili a livello 3 nel momento in cui si abilita lo stack (attraverso i loro indirizzi link local).
Sono stati quindi definiti alcuni indirizzi speciali di multicast per raggiungere determinate classi di host.

IPv6 101 (5) - Multicast

Alcuni esempi di indirizzi di Multicast.

Tutti i nodi IPv6:
  FF02::1 (link-local)

Tutti i router IPv6:
  FF02::2 (link-local)
  FF05::2 (site-local)

Tutti i server DHCPv6:
  FF02::1:2 (link-local) - RFC3315
  FF05::1:3 (site-local) - RFC3315

IPv6 101 (6) - Header

Confronto fra gli header IP:
Header IPv4 Header IPv6
(ma il diavolo è negli extension header!)

IPv6 101 (7) - Frammentazione

IPv4: Quando un pacchetto è troppo grande rispetto alla MTU del link sul quale deve essere trasferito, può venire frammentato da chi lo invia (host o router).
MTU minima: 576 byte massima: 65535 (216 - 1) byte.

IPv6: La frammentazione può avvenire solo nel nodo da cui ha origine il traffico, e la ricostruzione del pacchetto solo alla destinazione finale.
MTU minima: 1280 byte massima: 4294967295 (232 - 1) byte.

I router IPv6 non frammentano mai i pacchetti. Se ricevono pacchetti di dimensione maggiore della MTU del link di destinazione li scartano, e segnalano normalmente la situazione al nodo di origine con un messaggio ICMPv6 tipo 2 'Packet Too Big', in modo simile a quanto avviene in IPv4 quando è acceso il bit 'Don't Fragment'.
I nodi che originano traffico IPv6 devono effettuare una MTU discovery verso la destinazione per determinare la dimensione massima dei pacchetti da inviare. I protocolli di livello superiore devono se possibile limitare il payload. Se non è possibile, il nodo che origina il traffico può richiedere frammentazione e ricostruzione end-to-end utilizzando lo header opzionale 'Fragment'.

IPv6 101 (8) - Neighbor discovery

IPv4: ARP - Address Resolution Protocol.
Protocollo di livello intermedio 2/3.

IPv6: NDP - Neighbor Discovery Protocol.
Protocollo di livello 3, basato su appositi messaggi ICMPv6 (RFC4861):

IPv6 101 (9) - Configurazione degli indirizzi

IPv4: manuale, o via DHCP - Dynamic Host Configuration Protocol.

IPv6: manuale, via DHCPv6 oppure SLAAC - Stateless Address Auto-Configuration.

Principale differenza fra DHCP e DHCPv6:

La rotta di default non può essere assegnata via DHCPv6,

ma solo manualmente o via Router Advertisement (RA).
Sono ormai state bocciate cinque draft IETF (1, 2, 3, 4, 5) che proponevano di ripristinare la funzione di assegnazione della rotta di default nella risposta DHCPv6. Pare una battaglia persa...

IPv6 101 (10) - SLAAC

IPv6 101 (11) - EUI-64

IPv6 101 (12) - Protocolli di routing.

Protocolli di routing a disposizione:

RIP(v2) - solo IPv4.
RIPng(v2) - solo IPv6.

OSPF(v2) - solo IPv4.
OSPFv3(v2) - solo IPv6.

ISIS(v2) - IPv4 e IPv6.
Multiprotocol BGP(v2) - IPv4 e IPv6.

Principali differenze semantiche di IPv6 (1)

1. Ogni endpoint di rete ha sempre attivi indirizzi di rete multipli.

Principali differenze semantiche di IPv6 (2)

2. Assegnazione delle rotte.

Principali differenze semantiche di IPv6 (3)

3. Assegnazione degli indirizzi di rete e dei server DNS.

Differenze di IPv6 rilevanti per la sicurezza (1)

Il protocollo richiede alle implementazioni di trattare extension header del protocollo per funzioni che in precedenza erano opzionali (IPsec, QOS, supporto per mobile IP) e reimplementa varie funzioni (DHCP, neighbor discovery, anycast, multicast).
  • La comparsa di codice nuovo negli stack di rete è meravigliosa per chi è in cerca di vulnerabilità da sfruttare. Solo con l'avanzare dell'adozione e del tempo scopriremo quante ce ne sono.
Lo spazio di indirizzamento è più grande (128 bit - 340 undecilioni, 2120 indirizzi unicast teorici, 2112 indirizzi pubblici nella classe 2001:: già allocabili).
  • Uno scan brute force è più laborioso, potrebbe essere saggio assegnare indirizzi non contigui, ma ci sono altri sistemi per trovare possibili target sulla rete locale.
  • La collisione con indirizzi già allocati perde ogni efficacia (se mai ne ha avuta) nell'evidenziare accessi non autorizzati.

Differenze di IPv6 rilevanti per la sicurezza (2)

Molte funzioni utili al protocollo (Neighbor Discovery, MTU discovery, Mobility) vengono assorbite a livello 3 in ICMPv6. Dunque la comunicazione a livello 3 deve funzionare automaticamente almeno per macchine sullo stesso link.
  • Molti tipi di messaggi nuovi in ICMPv6, ed una RFC (4890) dedicata solo a specificare regole di firewall minimali per gli accessi IPv6.
  • L'operazione di Neighbor Discovery richiede un multicast locale.
  • Ma ICMPv6 proibisce esplicitamente di rispondere a/amplificare richieste inviate a indirizzi multicast (es: FF02::1, all-link-local-nodes, FF05::2, all-routers, vedi RFC2373).

I dispositivi intermedi non possono frammentare i pacchetti.
La MTU minima è di 1280 byte.
  • Nessuno però impedisce alle implementazione degli stack di creare autolesionisticamente frammenti più piccoli.

Differenze di IPv6 rilevanti per la sicurezza (3)

Ma... La grande quantità di header opzionali del protocollo potrebbe significare che il payload di livello superiore (con numeri di porta, ed altre informazioni utili per filtri e firewall) non si trova nel primo frammento e richiede di riassemblare i pacchetti.

A conclusione e parziale giustificazione di questo (preoccupante?) elenco di differenze, ricordiamo le tensioni in gioco nella progettazione di IPv6:
  1. Recuperare la trasparenza interna del livello di trasporto (soppressione di qualunque elemento intermedio stateful: NAT, Firewall).
  2. Facilitare la configurazione automatica del livello di trasporto.
  3. Consentire applicazioni di IP mobile.

La transizione IPv4→IPv6.

Scenario di transizione con host solo IPv6 (?) (1)


Scenario di transizione con host solo IPv6 (?) (2)


Della transizione: princìpi-guida.

  1. I servizi su IPv6 devono funzionare da subito tanto bene quanto i loro equivalenti su IPv4:
    • ⇒ "IPv6 days" in cui si ha il permesso di rompere qualcosa.
    • ¬⇒ che l'indirizzo dell ambìto web server ec.europa.eu cominci ad essere risolto su IPv6 senza essere raggiungibile via IPv6, come avvenuto il 6 Maggio 2014!
  2. Occorre mantenere ovunque la preferenza per IPv6.
    • Ogni eccezione è un sassolino che rallenta il treno della migrazione.
  3. Non bisogna avere fretta, ma agire proattivamente.
    • Gli strumenti di gestione della rete e di monitoring devono essere aggiornati.
    • Uno dei principali scenari problematici per la sicurezza è che le applicazioni vengano rappezzate in fretta e senza adeguata sperimentazione.
  4. Occorre resistere allo scoraggiamento, la transizione sta avvenendo.
    • "At Google we believe IPv6 is essential to the continued health and growth of the Internet".
    • "Replacing the Internet's plumbing will take some time, but the transition has begun".
    • Le statistiche di Google mostrano (per ora) un raddoppio ogni anno.
      Ora è il 10%, un anno fa il 5%, due anni fa il 2.5%...

getaddrinfo() e compagnia

Cosa dovrebbe sparire dal codice che usa sys/socket.h e netdb.h:

  1. gethostbyname()/getservbyname() → getaddrinfo()
  2. gethostbyaddr()/getservbyport() → getnameinfo()
  3. sockaddr_in(6) → sockaddr_storage
  4. Usi espliciti di struct in_addr senza casi paralleli per IPv6
  5. Manipolazioni di contenuti di sockaddr senza casi paralleli per IPv6
  6. inet_aton() → inet_pton()
  7. inet_ntoa() → inet_ntop()

getaddrinfo() - esempio

  #include <sys/socket.h>
  #include <netdb.h>
  char *destination, *service; /* Both can be numeric (address,port). */
  struct addrinfo ai_req, *ai_ans, *cur_ans;
 
  ai_req.ai_flags = 0;
  ai_req.ai_family = PF_UNSPEC;
  ai_req.ai_socktype = SOCK_STREAM;
  ai_req.ai_protocol = 0; /* Any protocol is OK */

  if (getaddrinfo(destination, service, &ai_req, &ai_ans)) == 0) {
    for (cur_ans = ai_ans; cur_ans != NULL; cur_ans = cur_ans->ai_next) {
      int fd_socket;
      if ((fd_socket=socket(cur_ans->ai_family, cur_ans->ai_socktype,
                            cur_ans->ai_protocol)) < 0) next;
      /* Do-what-needs-to-be-done. */
      break;
    }
  } else .....

Scelta degli indirizzi di origine e destinazione.

Dobbiamo imparare a memoria quanto segue?
Anche tradurlo lo rende ambiguo!

«The algorithms use several criteria in making their decisions. The combined effect is to prefer destination/source address pairs for which the two addresses are of equal scope or type, prefer smaller scopes over larger scopes for the destination address, prefer non- deprecated source addresses, avoid the use of transitional addresses when native addresses are available, and all else being equal, prefer address pairs having the longest possible common prefix. For source address selection, temporary addresses are preferred over public addresses. In mobile situations, home addresses are preferred over care-of addresses».
(estratto da RFC 6724, e si trova tale e quale nella vecchia 3484).

Indirizzi di origine e destinazione: chi sceglie?

La master policy table di RFC6724.

PrefixPrece-Label
dence
::1/128 50 0 Localhost
::/0 40 1 Tutta IPv6
::ffff:0:0/96 35 4 Tutta IPv4 ('mapped')
2002::/16 30 2 Tunnel 6to4 (mecc. di transizione)
2001::/32 5 5 Tunnel Teredo (mecc. di transizione)
fc00::/7 3 13 Unique Local Addresses
::/96 1 3 Indirizzi 'IPv4 compatible' - deprecati
fec0::/10 1 11 Indirizzi site-local - deprecati
3ffe::/16 1 12 6bone - defunto e deallocato
Se la 'label' dell'indirizzo di origine e di quello di destinazione è uguale non vengono considerate altre destinazioni anche con 'preference' più elevata.
RFC6724 dice che questa tabella DOVREBBE (SHOULD) essere configurabile.

/etc/gai.conf, ip -6 addrlabel e compagnia bella.

Caso clinico #1: Credevo-che-avrebbe-usato-IPv4.

  1. Avete sentito dire che abilitare il dual stack IPV4/IPv6 sui servizi centrali è una cosa buona, allora correte a farlo sul mail exchanger principale:
    mi.infn.it mail exchanger = 10 smtp1.mi.infn.it.
    smtp1.mi.infn.it has address 192.84.138.69
    smtp1.mi.infn.it has IPv6 address 2001:760:4210:1::a.
  2. Il MX inizia a ricevere posta da nodi sulla stessa sottorete che non hanno nessuna configurazione di IPv6, ma solo lo stack acceso:
    Mar 15 05:01:31 smtp1 sendmail[1244]: (...) relay=[IPv6:fe80::21d:9ff:fe10:faf9]
  3. IPv6 viene normalmente preferito a IPv4, così quando si scopre che l'indirizzo di destinazione appartiene ad un prefisso IPv6 'on-link' (cosa nota via Router Advertisement), la comunicazione può felicemente avvenire via IPv6, utilizzando lo scope link-local:
    fe80::20e:cff:fe4c:1ea5 lladdr 00:0e:0c:4c:1e:a5 REACHABLE
    2001:760:4210:1::a      lladdr 00:0e:0c:4c:1e:a5 REACHABLE
  4. Le cose potrebbero complicarsi se l'MX parla con office365, che da qualche mese differenzia le policy richiedendo obbligatoriamente SPF o DKIM per IPv6...

Caso clinico #2: l'indirizzo 6to4 e la rotta di default.

  1. La maggioranza silenziosa degli utenti di un link di rete ha IPv6 abilitato per default.
  2. Uno di essi prova ad accendere il servizio Windows Internet Connection Sharing (ICS).
  3. In assenza di appropriate contromisure (vedi RFC6104), tutti gli host con lo stack IPv6 attivo si trovano un indirizzo 6to4 pubblico ed una splendida rotta di default.
  4. Guardando alla policy di default specificata in RFC6724 questo è un problema ?
    • No, ma è un problema per la policy di default della vecchia RFC3484, nella quale tutta IPv4 si trova nella classe di precedenza più bassa!
  5. Se viene usata quella policy (vecchie versioni di S.O.), IPv6 viene preferito per contattare tutti i servizi il cui nome si risolve in un indirizzo IPv6 (oggi di fatto tutti i servizi noti) finché l'indirizzo e la rotta vengono deprecati (ad esempio inviando un contro-advertisement in multicast).
  6. Dal momento che di solito i tunnel IPv6-on-IPv4 sono filtrati nel router di frontiera (vero??) la comunicazione via IPv6 fallisce.
  7. Ma rimane possibile a chiunque annunciare indirizzi farlocchi e rotte per altri prefissi pubblici...

Caso clinico #3: l'indirizzo locale preferito.

  1. Su un host IPv6 provvisto di indirizzo IPv6 pubblico tutto funziona a meraviglia.
  2. Finché qualcuno decide di aggiungere un altro indirizzo pubblico, che viene messo in ordine prima dell'indirizzo a cui punta la risoluzione nel DNS:
    inet6 2001:760:4210:1::da:da01/64 scope global valid_lft forever
    inet6 2001:760:4210:1::d/64 scope global valid_lft forever.
  3. Improvvisamente, le verifiche dello hostname per le connessioni SSL che originano dalla macchina iniziano a fallire, perché il traffico ha origine dal nuovo indirizzo appena aggiunto, preferito dal sistema operativo.
  4. Soluzione: manipolare la tabella di preferenza dei prefissi per gli indirizzo di origine:
    prefix 2001:760:4210:1::da:0/112 label 8.
  5. Oppure assicurarsi che tutti i servizi registrino (bind()) le socket utilizzate per l'invio ad uno specifico indirizzo...

Caso clinico #4: il listener dual-stack.

  1. Nei sistemi con stack di rete ibrido IPv6/IPv4 (ad es. Linux), i servizi che cercano di chiamare bind() all'indirizzo IPv6 'unspecified' (:: - tutti zeri) si troveranno felicemente registrati sia su IPv6 che su IPv4 (a meno che utilizzino l'apposita opzione di setsockopt IPV6_V6ONLY).
  2. Solitamente però le socket in ascolto vengono ottenute richiedendo una socket passiva nella address family PF_UNSPEC.
  3. Glibc risponde a tale richiesta con un indirizzo di origine che risulti preferito per collegarsi alla destinazione localhost secondo le regole di RFC3484, che è stata resa obsoleta da RFC6724, che, come visto, afferma di non applicarsi a questo caso.
  4. La chiamata fino a qualche tempo fa restituiva una socket in listen su entrambi gli stack listening socket. Tuttavia un commit del 2008 su glibc ha corretto un baco: all'indirizzo IPv6 'localhost' (::1) non veniva assegnato lo scope link-local, come richiesto da RFC4291.
  5. Risultato: dal momento che nelle regole di default di RFC6724 l'indirizzo IPV4 di localhost ha la stessa 'label' di tutto il resto di IPv4 ora, senza cambiare una riga di codice, viene preferito un binding solo su IPv4!

Palle degli occhi felici ?

Bibliografia