Tunneling IPv6 con OpenBSD


by Kundera - kundera@tiscali.it

Questo piccolo documento ha lo scopo di spiegare la procedura per realizzare e gestire un tunnel IPv6 over IPv4 con il sistema operativo OpenBSD.

Inanzitutto per poter creare un tunnel di questo tipo dovete avere il supporto IPv6 nel kernel del vostro sistema OpenBSD che è incluso a partire dalla versione 2.7 anche nel kernel che mette a disposizione l'installazione, il cosidetto "GENERIC". In ogni caso se non avete il supporto ma avete al meno la versione 2.7 ricompilate includendo nel file di configurazione le seguenti direttive :

option INET6 #IPv6 (needs INET)

per il supporto IPv6 KAME project, che ha bisogno anche del supporto IPv4.

pseudo-device gif 4 #IPv[46] over IPv[46] tunnel (RFC1933)

per la creazione delle interfacce di tunneling "gif" dove 4 è il numero di interfacce che vorrete usare (gif0,gif1,gif2, etc..).

Una volta pronti digitate "ifconfig -a" per vedere se sono disponibili le sopracitate interfacce di tunneling generico, vediamo nel mio sistema :

bash#ifconfig -a

lo0: flags=8009 mtu 33224
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3
inet6 ::1 prefixlen 128
inet 127.0.0.1 netmask 0xff000000
lo1: flags=8008 mtu 33224
pflog0: flags=0<> mtu 33224
sl0: flags=c010 mtu 296
sl1: flags=c010 mtu 296
ppp0: flags=8010 mtu 1500
ppp1: flags=8010 mtu 1500
tun0: flags=10 mtu 3000
tun1: flags=10 mtu 3000
enc0: flags=0<> mtu 1536
bridge0: flags=0<> mtu 1500
bridge1: flags=0<> mtu 1500
vlan0: flags=0<> mtu 1500
vlan1: flags=0<> mtu 1500
gre0: flags=8010 mtu 1450
gif0: flags=8010 mtu 1280
gif1: flags=8010 mtu 1280
gif2: flags=8010 mtu 1280
gif3: flags=8010 mtu 1280
ep1: flags=8863 mtu 1500
media: Ethernet autoselect (10baseT)
status: active
inet 150.1.1.71 netmask 0xffff0000 broadcast 150.1.255.255
inet6 fe80::250:daff:fe53:6f2e%ep1 prefixlen 64 scopeid 0x14

si, come vedete abbiamo a disposizione 4 interfacce gif. Rimane da dire un'altra cosa fondamentale, per creare un tunnel IPv4-IPv6 abbiamo bisogno di una macchina che dall'altra parte del tunnel decapsuli i pacchetti IPv6 e li inoltri nella rete mondiale IPv6 di testing 6BONE. Ci sono diversi servizi di tunnel-broker gratuiti in Italia e all'estero tra cui :

http://www.ngnet.it
http://www.6bone.it
http://www.freenet6.net

Una volta registrati il gestore del tunnel broker ci fornirà gli indirizzi che dobbiamo configurare sul nostro sistema. Ad esempio con il t.b. di Telecom Italia Lab avremo delle informazioni tipo queste :

Tunnel Info

Server IPv4 Address 150.1.1.71
Server IPv6 Address 2001:06b8:0000:0400::0dc3
Server IPv6 Link Local Address fe80::a3a2:aaad
Client IPv4 Address 212.210.11.4
Client IPv6 Address 2001:06b8:0000:0400::0dc2
Client IPv6 Link Local Addr fe80::d4d2:0b04
Expire Date. 03-05-2002


Procediamo inanzitutto alla creazione del tunnel IPv4 sull'interfaccia gif in questo modo:

bash# ifconfig gif0 tunnel 150.1.1.71 163.162.170.173

dove specifichiamo gli endpoint IPv4 del tunnel, i pacchetti IPv6 all'interno del tunnel generati dal nostro sistema saranno incapsulati in datagrammi IPv4 con indirizzo sorgente 150.1.1.71 e destinazione 163.162.170.173 . Da notare che se specifichiamo un'altro indirizzo e non effettivamente il nostro (150.1.1.71) i pacchetti usciranno con quello "spoofato" :) . Successivamente creiamo la "punto-punto" IPv6 con gli indirizzi assegnati dal tunnel broker sulla nostra interfaccia con il comando:

bash# ifconfig gif0 inet6 2001:06b8:0000:0400::0dc2 2001:06b8:0000:0400::0dc3 prefixlen 128

dato che ci hanno assegnato un'unico indirizzo IPv6 e non una piccola subnet mettiamo tranquillamente come lunghezza di prefisso 128bit (prefixlen 128), un'po' come subnet /32 o 255.255.255.255 di IPv4.Vediamo lo stato dell'interfaccia gif0 :

bash# ifconfig gif0
gif0: flags=8051 mtu 1280
physical address inet 150.1.1.71 --> 163.162.170.173
inet6 fe80::250:daff:fe53:6f2e%gif0 -> :: prefixlen 64 scopeid 0x10
inet6 2001:6b8:0:400::dc2 -> 2001:6b8:0:400::dc3 prefixlen 128

A questo punto siamo in grado di vedere solo il nodo all'altro capo del tunnel infatti se lo pinghiamo dovremmo ottenere la risposta :

bash# ping6 2001:06b8:0000:0400::0dc3 PING6(56=40+8+8 bytes) 2001:6b8:0:400::dc2 --> 2001:6b8:0:400::dc3
16 bytes from 2001:6b8:0:400::dc3, icmp_seq=0 hlim=64 time=87.649 ms
16 bytes from 2001:6b8:0:400::dc3, icmp_seq=1 hlim=64 time=43.838 ms
16 bytes from 2001:6b8:0:400::dc3, icmp_seq=2 hlim=64 time=42.665 ms
16 bytes from 2001:6b8:0:400::dc3, icmp_seq=3 hlim=64 time=38.515 ms

--- 2001:06b8:0000:0400::0dc3 ping6 statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/std-dev = 38.515/53.167/87.649/20.006 ms

Per vedere tutta la 6Bone dobbiamo infine aggiungere la route statica di default per far si che il nostro tunnel-broker sia il default gateway con il solito comando route ma specificando che si tratta di una statica IPv6 :

bash# route add -inet6 default 2001:6b8:0:400::dc3

Siamo ora in grado di raggiungere tutti gli host della 6Bone e per quanto riguarda la risoluzione dei nomi in indirizzi IPv6 il sistema è già a posto perchè la risoluzione viene fatta tramite query al DNS in IPv4 che aggiunge, se disponibili, anche gli indirizzi IPv6.
Per rendere il tutto più veloce possiamo naturalmente creare e disattivare il tunnel con 2 script che vanno a prendere la prima interfaccia gif libera, script di creazione del tunnel :

#!/bin/sh
gif_ifaces=`ifconfig -a|grep -w gif[0-9]*|grep -v UP| grep -v inet6 | awk -F":" '{print $1}'`
gif_iface=`echo $gif_ifaces|awk '{print \$1'}`
if [ -z $gif_iface ]; then
echo "No gif interfaces available."
echo "Tunnel can't be configured"
exit
fi
ifconfig $gif_iface tunnel 150.1.1.71 163.162.170.173 >> /tmp/tb.log
ifconfig $gif_iface inet6 2001:06b8:0:0400::0dc2 2001:06b8:0:0400::0dc3 prefixlen 128 >> /tmp/tb.log
route add -inet6 default 2001:06b8:0:0400::0dc3
echo "2001:06b8:0000:0400:0000:0000:0000:0dc2 $gif_iface" >> /tmp/tb.gif

e lo script per disattivarlo :

#!/bin/sh
iface=`grep 2001:06b8:0000:0400:0000:0000:0000:0dc2 /tmp/tb.gif | awk '{print $2}'`
#iface=`netstat -nr -f inet6 | grep 2001:06b8:0000:0400:0000:0000:0000:0dc3|awk '{print $4}'`
gif_iface=`echo $iface | awk '{print $1}'`
if [ ! -z $gif_iface ]; then
ifconfig $gif_iface inet6 delete 2001:06b8:0000:0400:0000:0000:0000:0dc2
ifconfig $gif_iface deletetunnel
ifconfig $gif_iface down
route delete -inet6 default
cp /tmp/tb.gif /tmp/tmp.gif
grep -wv 2001:06b8:0000:0400:0000:0000:0000:0dc2 /tmp/tmp.gif > /tmp/tb.gif
rm /tmp/tmp.gif
fi

OpenBSD è anche in grado di fare da router e firewall IPv6, infatti se il nostro tunnel-broker ci assegna non un singolo indirizzo ma una subnet IPv6 possiamo configurare OpenBSD per fargli instradare il traffico proveniente dalla nostra LAN IPv6 nel tunnel che raggiunge la 6Bone facendo della nostra la LAN una vera e propria zona della rete di testing IPv6. Il t.b. che ci può dare questo tipo di accesso è ad esempio Edisontel che ci assegna una subnet di 16 indirizzi (prefisso di 124 bit, infatti abbiamo 4 bit per indirizzare i nostri host e quindi 16 indirizzi disponibili). Dopo aver fatto le registrazione Edisontel ci comunica che la nostra subnet ? ad esempio 3FFE:8172::D:1c10/124 e l'endpoint IPv4 del tunnel 62.94.46.106 . Procediamo a configurare il solito tunnel con :

bash# ifconfig gif0 tunnel 150.1.1.71 62.94.46.106
bash# ifconfig $gif0 inet6 3ffe:8172::d:1c10 3ffe:8172::d:0 prefixlen 124
bash#route add -inet6 default 3ffe:8172::d:0 add net default: gateway 3ffe:8172::d:0

Abbiamo utilizzato il primo indirizzo per il tunnel ma lo assegnamo anche all'interfaccia ethernet per far si che il default gateway sia raggiungibile anche dagli host sulla LAN con questo ifconfig :

bash# ifconfig ep1 inet6 alias 3ffe:8172::d:1c10 prefixlen 124

Vediamo lo stato dell'interfaccia :

bash#ifconfig ep1
ep1: flags=8863 mtu 1500
media: Ethernet autoselect (10baseT)
status: active
inet 150.1.1.71 netmask 0xffff0000 broadcast 150.1.255.255
inet6 fe80::250:daff:fe53:6f2e%ep1 prefixlen 64 scopeid 0x14
inet6 3ffe:8172::d:1c10 prefixlen 124

Abilitiamo l'instradamento dei pacchetti con una sysctl per trasformare la nostra box in un router :

bash# sysctl -w net.inet6.ip6.forwarding=1
net.inet6.ip6.forwarding: 0 -> 1

Assegnamo gli indirizzi IPv6 rimanenti (3ffe:8172::d:1c11,3ffe:8172::d:1c12,etc .. ) agli altri host della LAN ,settiamo come default gateway 3ffe:8172::d:1c10 e siamo a posto. Rimane da configurare, per essere più sicuri, il firewalling sull'interfaccia del tunnel che su OpenBSD 3.0 con Packet Filter può essere configurato in questo modo nel file di configurazione /etc/pf.conf :

# $OpenBSD: pf.conf,v 1.2 2001/06/26 22:58:31 smart Exp $
#
# See pf.conf(5) for syntax and examples

# pass all packets in and out (these are the implicit last two rules)
# pass in all
# pass out all

block out on gif0 inet6 all
block in on gif0 inet6 all
block in quick on gif0 inet6 from 3ffe:8172::d:1c10/124 to any
pass out on gif0 inet6 proto tcp from any to any flags S/SA keep state
pass out on gif0 inet6 proto udp all keep state
pass out on gif0 inet6 proto ipv6-icmp all keep state
pass in on gif0 inet6 proto tcp from any to 3ffe:8172::d:1c13 port = 80 keep state

In questo esempio abbiamo bloccato in ingresso e uscita tutto sulla gif0 come regola di default, con la terza riga blocchiamo tutti i pacchetti provenienti dall'esterno con indirizzo sorgente quello della nostra subnet di 16 indirizzi (quindi un probabile tentativodi spoofing), poi abilitiamo tutte le connessioni TCP in uscita con controllo della connessione ,tutte le porte in uscita UDP e tutti i pacchetti in uscita ICMPv6. Con l'ultima riga abilitiamo in ingresso solo la porta 80 con controllo della connessione se ad esempio abbiamo un web server IPv6 su una delle nostre macchine interne (ad esempio sulla 3ffe:8172::d:1c13).
Applichiamo le regole appena viste e abilitiamo il firewall con:

bash#pfctl -R /etc/pf.conf
bash#pfctl -e


Links utili :

OpenBSD Packet Filter : http://www.benzedrine.cx/pf.html
KAME Project : http://www.kame.net
6Bone, testbed for deployment of IPv6 : http://www.6bone.net