Table of Contents

IPv6

Struttura di un indirizzo IPv6

L'indirizzo è lungo 128 bit, la prima metà è la parte network (di cui i primi bit indicano il tipo), la seconda metà è la parte interface. Per generare automaticamente la parte interface può essere usato una parte del MAC address, generando il cosiddetto Extended Unique Identifier (EUI-64).

Tipi di indirizzo IPv6

Per abbreviare un indirizzo IPv6 è possibile sostituire la sequenza :0: con :: e collassare una sequenza di due punti con solo il primo e l'ultimo.

Disabilitare IPv6

Da Debian Squeeze:

echo net.ipv6.conf.all.disable_ipv6=1 > /etc/sysctl.d/disableipv6.conf

Aggiungere e togliere un indirizzo IPv6

Per aggiungere e togliere un indirizzo IPv6 da riga di comando (non persiste al reboot):

ip -6 addr add <ipv6address>/<prefixlength> dev <interface>
ip -6 addr del <ipv6address>/<prefixlength> dev <interface>

Per aggiungere e togliere una rotta IPv6:

ip -6 route add <ipv6network>/<prefixlength> via <ipv6address> [dev <device>]
ip -6 route del <ipv6network>/<prefixlength> via <ipv6address> [dev <device>]
ip -6 route add default via <ipv6address> [dev <device>]
ip -6 route del default via <ipv6address> [dev <device>]

Configurazione automatica

La configurazione è integrata nel protocollo IPv6. La configurazione automatica viene detta stateless, cioè avviene senza il ricorso a risorse esterne.

Il kernel fornisce le seguenti interfacce per controllare la configurazione automatica, normalmente i meccanismi sono tutti attivi:

/proc/sys/net/ipv6/conf/eth0/accept_ra Decide se usare l'autoconfigurazione, compreso il rilevamento di un router.
/proc/sys/net/ipv6/conf/eth0/autoconf Se viene individuato un router, genera un indirizzo IPv6 utilizzando il MAC address.
/proc/sys/net/ipv6/conf/eth0/use_tempaddr Se viene individuato un router, genera un indirizzo IPv6 casuale temporaneo.

Quindi se esiste un host che annuncia la configurazione IPv6 (ad esempio un host GNU/Linux che esegue radvd, Router Advertisement Daemon), gli host nella stessa LAN si assegnano automaticamente un indirizzo IPv6 valido (ma non il default gateway).

Per modificare uno di quei parametri creare un file /etc/sysctl.d/90-local-ipv6.conf con ad esempio:

net.ipv6.conf.eth1.accept_ra=0

Per rendere immediatamente attive le modifiche:

cat /proc/sys/net/ipv6/conf/eth1/accept_ra 
1
sysctl --system
cat /proc/sys/net/ipv6/conf/eth1/accept_ra 
0

Configurazione manuale

Anzitutto si deve disabilitare la configurazione automatica. Con Debian è necessario forzare il caricamento del modulo kernel IPv6 aggiungendo in /etc/modules:

# Force IPv6 preload, so that /etc/sysctl.d/local.conf will be
# parsed when the protocol is already available.
ipv6

e aggiungere una riga in /etc/sysctl.d/local.conf oppure in /etc/sysctl.conf:

net.ipv6.conf.default.autoconf=0
net.ipv6.conf.default.accept_ra=0

Il modulo ipv6 va caricato manualmente perché lo script /etc/init.d/procps.sh (che interpreta /etc/sysctl.conf) viene eseguito troppo presto nella fase di boot, quando ipv6 ancora non è disponibile e quindi l'impostazione non avrebbe effetto. Inoltre si deve agire su default piuttosto che su eth0, perché lo script viene eseguito prima che l'interfaccia sia disponibile.

Per configurare staticamente l'indirizzo IP e il default gateway si aggiunge una sezione in /etc/network/interfaces:

auto eth0

iface eth0 inet static
        address 62.48.51.14
        netmask 255.255.255.0
        broadcast 62.48.51.255
        gateway 62.48.51.1


iface eth0 inet6 static
        #pre-up modprobe ipv6
        address 2a01:6a0:ff:59::14
        netmask 64
        gateway 2a01:6a0:ff:59::1

Il comando pre-up non è necessario in questo caso, perché abbiamo fatto il preload in /etc/modules.

Al reboot si avranno due indirizzi su eth0, uno IPv4 e uno IPv6:

eth0      Link encap:Ethernet  HWaddr 00:50:FC:FF:1D:3E  
          inet addr:62.48.51.14  Bcast:62.48.51.255  Mask:255.255.255.0
          inet6 addr: fe80::250:fcff:feff:1d3e/64 Scope:Link
          inet6 addr: 2a01:6a0:ff:59::14/64 Scope:Global
          ...

Anche rotte predefinite ce ne saranno due:

ip -6 route show
2a01:6a0:ff:59::/64 dev eth0  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
fe80::/64 dev eth0  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
ff00::/8 dev eth0  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
default via 2a01:6a0:ff:59::1 dev eth0  metric 1  mtu 1500 advmss 1440 hoplimit 4294967295
route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
62.48.51.0      0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         62.48.51.1      0.0.0.0         UG    0      0        0 eth0

Neighbors table

Con IPv6 non si ha la tabella di ARP con associazione IPv4 - MAC. Qualcosa di equivalente sono i vicini di IPv6:

ip -6 neigh show
fe80::223:5ff:fe1d:3ee8 dev eth0 lladdr 00:23:05:1d:3e:e8 router DELAY
2a01:6a0:ff:59::1 dev eth0 lladdr 00:23:05:1d:3e:e8 router REACHABLE

Per dimenticare l'associazione tra indirizzo IPv6 e il MAC address (link layer address):

ip -6 neigh del fe80::223:5ff:fe1d:3ee8 lladdr 00:23:05:1d:3e:e8 dev eth0
ip -6 neigh del 2a01:6a0:ff:59::1 lladdr 00:23:05:1d:3e:e8 dev eth0

Vediamo come funziona la scoperta di un vicino di rete:

ping6 2a01:6a0:ff:59::1
tcpdump -i eth0 -t -e -n 'icmp6'
00:50:fc:ff:1d:3e > 33:33:ff:00:00:01, ethertype IPv6 (0x86dd), length 86: 2a01:6a0:ff:59::14 > ff02::1:ff00:1: ICMP6, neighbor solicitation, who has 2a01:6a0:ff:59::1, length 32
00:23:05:1d:3e:e8 > 00:50:fc:ff:1d:3e, ethertype IPv6 (0x86dd), length 86: 2a01:6a0:ff:59::1 > 2a01:6a0:ff:59::14: ICMP6, neighbor advertisement, tgt is 2a01:6a0:ff:59::1, length 32
00:50:fc:ff:1d:3e > 00:23:05:1d:3e:e8, ethertype IPv6 (0x86dd), length 118: 2a01:6a0:ff:59::14 > 2a01:6a0:ff:59::1: ICMP6, echo request, seq 1, length 64
00:23:05:1d:3e:e8 > 00:50:fc:ff:1d:3e, ethertype IPv6 (0x86dd), length 118: 2a01:6a0:ff:59::1 > 2a01:6a0:ff:59::14: ICMP6, echo reply, seq 1, length 64

Cioè:

  1. Viene mandato una neighbor solicitation all Solicited-node multicast address (link-local scope) con prefisso di 104 bit ff02::1:ff00 e suffisso di 24 bit preso dall'indirizzo destinazione.
  2. Il MAC address del destinatario è un multicast 33:33:ff:00:00:01, che dovrebbe essere registrato sull'host destinazione.
  3. L'host risponde con il proprio MAC address annunciando il target IPv6.

Per vedere gli indirizzi multicast registrati su un host:

ip maddr show
1:      lo
        inet  224.0.0.1
        inet6 ff02::1
2:      eth0
        link  33:33:ff:00:00:06
        link  33:33:ff:ba:bb:ec
        link  01:00:5e:00:00:01
        link  33:33:00:00:00:01
        inet  224.0.0.1
        inet6 ff02::1:ff00:6
        inet6 ff02::1:ffba:bbec
        inet6 ff02::1

Ping per tutti gli host nel link-local scope:

ping6 ff02::1%eth0

Ping per tutti i router nel link-local scope:

ping6 ff02::2%eth0

Filtro multicast su switch

Alcuni switch hanno un filtro sui pacchetti multicast abilitato. Questo impedisce il funzionamento del protocollo Neighbor Discovery Protocol, per cui il ping6 funziona sugli host remoti, ma non su quelli locali.

Ad esempio sullo switch 3Com 4228G bisogna disabilitare il multicastFilter/igmp.

Shorewall6: iptables con IPv6

Vedere Shorewall IPv6 Support.

Un firewall basato su iptables, come Shorewall, non ha alcun effetto sul traffico IPv6. Considerato che con IPv6 l'indirizzo assegnato ad un host ha scope global (cioè è raggiungibile da tutta internet) è chiaro che sul router/firewall è opportuno mettere alcune regole, come minimo bisogna bloccare tutto il traffico dall'esterno verso l'interno.

Con Debian è sufficiente installare il pacchetto shorewall6 che affianca il pacchetto shorewall e gestisce IPv6 in modo del tutto separato da IPv4.

L'unica verifica da fare sullo Shorewall IPv4 è che in /etc/shorewall/shorewall.conf sia impostato:

DISABLE_IPV6=No

Copiare dagli esempi (contenuti in /usr/share/doc/shorewall6/default-config/ oppure in /usr/share/shorewall6/configfiles/) alcuni file di configurazione, in generale servono questi:

/etc/shorewall6/zones

fw      firewall
net     ipv6

/etc/shorewall6/interfaces

net     eth0

/etc/shorewall6/policy

fw      all     ACCEPT
all     all     REJECT          info

/etc/shorewall6/rules

Ping(ACCEPT)    all                        all
AllowICMPs      all                        all
ACCEPT          net                        fw    tcp     ssh,smtp,domain,www,pop3,imap2,imaps,https
ACCEPT          net                        fw    udp     domain,openvpn
ACCEPT          net:<2a01:4f8:d13:c03::2>  fw    tcp     5432

Quindi impostare in /etc/default/shorewall6:

startup=1

IPv6 su PPP

Alcuni provider forniscono indirizzi IPv6 sulla normale connessione ADSL. In generale funziona l'autoconfigurazione durante la negoziazione del PPPoE (PPP over Ethernet). Qui di seguito le note per la configurazione della connessione di un host basato su Debian 9 Stretch.

Configurazione manuale

Se lo stack PPP non è opportunamente configurato, è possibile procedere alla configurazione manuale dell'indirizzo IPv6 e del relativo default gateway dopo che la connessione è stabilita. È ovviamente necessario conoscere i parametri che dovrebbero essere forniti dal provider. Ecco un esempio dei comandi da eseguire:

ip -6 addr add 2a02:1970:af32:421::1/64 dev ppp0
ip -6 route add default via fe80::a64c:32fe:ac3b:9480 dev ppp0

Configurazione automatica

La configurazione standard di una connessione PPPoE con Debian prevede la creazione di una istanza in /etc/network/interfaces:

auto adsl
iface adsl inet ppp
    provider dsl-provider

Nel file /etc/ppp/peers/dsl-provider (oltre ai normali parametri user e remotename) si aggiungere il parametro:

+ipv6

Per ottenere la configurazione automatica si sfrutta il protocollo Stateless Address Autoconfiguration SLAAC, l'interfaccia ppp deve accettare il Router Advertisements.

Il kernel di Linux espone il parametro accept_ra delle varie interfacce di rete tramite lo pseudo filesystem /proc/sys/net/ipv6/conf/. Questi sono i valori possibili:

0 Do not accept Router Advertisements.
1 Accept Router Advertisements if forwarding is disabled (default).
2 Overrule forwarding behaviour. Accept Router Advertisements even if forwarding is enabled.

Il valore predefinito 1 ovviamente non va bene per un firewall che effettua il forward dei pacchetti da una LAN verso internet.

Si potrebbe impostare a 2 il valore di default con questo comando:

echo 2 > /proc/sys/net/ipv6/conf/default/accept_ra

In questo modo - quando viene attivata l'interfaccia ppp0 - si otterrebbe l'autoconfigurazione IPv6. Ma non vogliamo cambiare il valore predefinito per tutte le interfacce attivate; vogliamo una soluzione più mirata. Neanche intervenire su /etc/network/interfaces (tramite le clausole pre-up e/o up) è consigliabile, perché la tempistica con cui i comandi vengono eseguiti va in conflitto con i tempi che il kernel richiede a fare il setup dell'interfaccia.

Sembra che la soluzione migliore sia quella di creare un file /etc/ppp/ipv6-up.d/accept_ra (deve essere eseguibile) con questo contenuto:

#!/bin/sh
# Accept Router Advertisements; autoconfigure using them.
echo 2 > "/proc/sys/net/ipv6/conf/${PPP_IFACE}/accept_ra"

NOTA: invece di utilizzare il comando echo è possibile, in alternativa, usare il comando sysctl come in questo esempio:

sysctl -w net.ipv6.conf.ppp0.accept_ra=2

Riferimenti web

Vedere questo post: Linux, IPv6, router advertisements and forwarding, nel quale si legge:

By default, a Linux host on an IPv6 network will listen for and solicit router advertisements in order to choose an IPv6 address for itself and to set up its default route. This is referred to as stateless address autoconfiguration (SLAAC).

In this context, what makes the difference between router or not are the settings of the /proc/sys/net/ipv6/conf/*/forwarding files (or the net.ipv6.conf.*.forwarding sysctl). If you turn your host into a router by setting one of those to “1”, you may find that your host removes any IPv6 address and default route it learnt via SLAAC.