[Ninux-Calabria] Integrare un tunnel GRE in OpenWRT

Stefano De Carlo stefanauss a gmail.com
Ven 6 Giu 2014 13:07:05 CEST


Ciao a tutti,

[lista hlcs in copia perchè ci sono info specifiche sulla rete 10.87.1.0/24]

siccome dalle compilazioni seriali ci vuole una pausa, a prescindere
dalle decisioni finali su cosa finirà in NinucsWRT4MiB,che scaturiranno
solo dopo test approfonditi, mi sono dedicato a capire come fosse
possibile integrare un tunnel GRE all'interno di OpenWRT.

Premessa: per chi si fosse perso dei passaggi, in Ninux Calabria serve
identificare dei meccanismi di tunneling ben definiti (da integrare poi
nel nostro firmware), per consentire ai nodi che lo vogliano di
scegliersi il proprio default gw sulla rete. Leggi: condivisione ADSL
"privata", una delle feature che più pubblicizziamo quando parliamo di
Ninucs.
GRE è il protocollo di tunneling più semplice e leggero, ci naviga
persino in 4MiB di Flash. Ha tanti contro però: 0 sicurezza, nessuna
autenticazione (very very bad) né criptazione (meno bad, d'altronde
Ninux rinuncia ai link wireless criptati per definizione), mancanza di
supporto per più client contemporaneamente (continua a leggere),
integrazione in Luci tutta da fare (questa mail è un inizio).

Requisiti: c'abbiamo bisogno del pacchetto kmod-gre (e kmod-gre6) per il
supporto al tunneling IP-in-IP, ma poi serve anche il binario ip di
iproute2 per impostare il tunneling. Lo si può avere o installando
direttamente il pacchetto "ip" oppure compilando busybox con le apposite
opzioni per embeddarlo (grazie Peppe per la dritta). La differenza in
dimensioni però era irrisoria, allora ho optato per il binario standalone.

Passo direttamente all'HowTo, lo commento in seguito.
Nel mio esempio
$IP_BACKBONE: 172.17.87.20, router a terra di Spax
$IP_ROUTER_CLIENT: 10.87.1.2, access point wireless Hacklab
Server: Attitude Adjustment
Clent: Barrier Breaker

== ENDPOINT SERVER ==

Luci > System > Startup > Local Startup (oppure: Terminale > /etc/rc.local)

# GRE TUNNELING (SERVER)
# Aggiungere le seguenti righe, prima di exit0
# Creazione del tunnel
ip tunnel add tun0 mode gre local $IP_BACKBONE remote $IP_ROUTER_CLIENT
ttl 64
# Tiriamo su l'interfaccia
ifconfig tun0 up
# Settiamo l'indirizzo del tunnel, 100.65.0.0/24 è la subnet designata
# In Barrier Breaker se qui osiamo esplicitareil CIDR lo script fallisce.
ifconfig tun0 100.65.0.2
# Consentiamo il traffico multicast, che GREsupporta
ifconfig tun0 multicast
# Scegliamo l'altro endpoint, il client chiaramente
ifconfig tun0 pointopoint 100.65.0.1
# Workaround per bug Attitude Adjustment
# Forse un reload potrebbe bastare, ma suvvia.
/etc/init.d/network restart

Terminale > /etc/hotplug.d/iface/90-gre

#!/bin/sh
# Workaround per PtP che si resetta a sè stesso.
[ "$ACTION" == "ifup" -a "$INTERFACE" == "GRE" ] && {
    ifconfig tun0 pointopoint 100.65.0.1
    }

Luci > Network > Interfaces

Add New Interface.
Device: tun0 se c'è già o scegliamo Custom e lo scriviamo noi
direttamente.Niente bridge.
Protocol: Static Address.
IP: 100.65.0.2
Netmask: 255.255.255.0
Firewall Settings > Assegniamo ad una nuova zona GRE.
Save & Apply.

Luci > Network > Firewall > General Settings

Aggiungiamo/Modifichiamo un Interzone Forwardings GRE => WAN,
probabilmente potremo editare quello automatico GRE => REJECT.
Allow Traffic to Destination Zones: selezioniamo WAN
Input, Output, Forward: tutto ACCEPT
Abilitiamo MSS Clamping e Masquerading.
Save & Apply.

Fatto. Al riavvio dovremmo avere il lato server col tunnel tirato su e
pronto.

== ENDPOINT CLIENT ==

Luci > System > Startup > Local Startup (oppure: Terminale > /etc/rc.local)

# GRE TUNNELING (CLIENT)
# Aggiungere le seguenti righe, prima di exit0
# Creazione del tunnel
ip tunnel add tun0 mode gre local $IP_ROUTER_CLIENTremote $IP_BACKBONEttl 64
# Tiriamo su l'interfaccia
ifconfig tun0 up
# Settiamo l'indirizzo del tunnel, 100.65.0.0/24 è la subnet designata
# In Barrier Breaker se qui osiamo esplicitare il CIDR lo script fallisce.
ifconfig tun0 100.65.0.2
# Consentiamo il traffico multicast, che GRE supporta
ifconfig tun0 multicast
# Scegliamo l'altro endpoint, il serverchiaramente
ifconfig tun0 pointopoint 100.65.0.2
# Workaround per bug Attitude Adjustment
# Commentato, non sembra accadere in BB.
# /etc/init.d/network restart

Terminale > /etc/hotplug.d/iface/90-gre

#!/bin/sh
# Workaround per PtP che si resetta a sè stesso.
[ "$ACTION" == "ifup" -a "$INTERFACE" == "GRE" ] && {
    ifconfig tun0 pointopoint 100.65.0.2
    # Nel caso avessimo problemi in presenza di static routes.
    # route del default
    # route add default gw 100.65.0.1
    }


Luci > Network > Interfaces

Add New Interface.
Device: tun0 se c'è già o scegliamo Custom e lo scriviamo noi
direttamente. Niente bridge.
Protocol: Static Address.
IP: 100.65.0.1
Netmask: 255.255.255.0
Gateway: 100.65.0.2
Firewall Settings > Assegniamo ad una nuova zona GRE.
Save & Apply.

Luci > Network > Firewall > General Settings

Aggiungiamo/Modifichiamo un Interzone Forwardings LAN + GRE => WAN,
probabilmente potremo editare quello automatico LAN => WAN.
Allow Traffic from Sources Zones: selezioniamo GRE
Input, Output, Forward: tutto ACCEPT

Luci > Network > Firewall > General Settings

Aggiungiamo/Modifichiamo un Interzone Forwardings GRE => REJECT,
probabilmente potremo editare quello già presente.
Input/Output/Forward: ACCEPT/ACCEPT/REJECT
Allow Traffic to Destination Zones: selezioniamo WAN
Input, Output, Forward: tutto ACCEPT
Abilitiamo MSS Clamping e Masquerading.
Lasciamo il resto com'è.
Save & Apply.

Fatto. Al riavvio dovremmo avere il lato client col tunnel tirato su e
pronto.

== NOTE==

Purtroppo Luci non supporta nativamente i tunnel GRE, cosa che a sua
volta deriva dal mancato supporto in UCI. Non c'è un "option proto gre"
da inserire da qualche parte. Quindi ho cercato di usare al massimo
possibile gli internals di OpenWRT in modo da avere qualcosa di
affidabile, stabile e anche facile da usare una volta configurato la
prima volta.

Tirare su un tunnel è facile, serve solo che i computer possano
raggiungersi a vicenda. Provate su due computer della vostra LAN,
seguendo questo:
http://tier.cs.berkeley.edu/drupal/howto/ip-tunnel-using-gre-on-linux

Il caricamento del modulo gre crea nel kernel delle interfacce dormienti
come ip6tnl0, gre0, gretap0, ip6gre0. Tuttavia non sono riuscito a
modificarne i parametri e farne uso diretto, ed ho dovuto optare per
creare un nuovo tun0.

Il tunnel viene creato al boot-time dalle istruzioni in /etc/rc.local.
Particolarità:
* Luci è in grado di dare l'IP statico all'interfaccia successivamente,
tuttavia è meglio farlo a mano anche al boot perché altrimenti rifiuta
di accettare il comando per selezionare l'endpoint.
* In AA anche se al boot la creazione del tunnel avviene correttamente
(tunnel c'è, interfacce up, parametri ok), la comunicazione non avviene.
Con gli stessi comandi, dati a boot già avvenuto, tutto a posto. Non ho
trovato la causa, ma ho scoperto che aggiungendo un restart del network
dopo la creazione del boot, tutto ok. Probabilmente anche un reload
sarebbe sufficiente, da provare. In BB questa situazione non si presenta
e il tunnel è instaurato correttamente all'avvio.

Una volta che al boot ci troviamo il tunnel, possiamo gestirlo con le
Networks di Luci con protocollo "static", che meglio traduce le
caratteristiche dei link GREassimilandoli ad un normalelink
ethernet.Diventa possibile assegnare indirizzi, gateway, netmask, far
girare DHCP, assegnare zone di firewall, tutto da Luci. :)
L'unica fregatura avviene quando vogliamo spegnere/riaccendere
l'interfaccia da Luci usando Connect/Stop. Se lo facciamo, lui fa
ifup/ifdown corretto, ma il tunnel è sputtanato perché il pointopoint
dell'interfaccia viene resettato all'interfaccia stessa e non all'altro
endpoint.
Per fortuna esiste un internals di OpenWRT che fa al caso nostro:
Hotplug(http://wiki.openwrt.org/doc/techref/hotplug). Sono una serie di
script che vengono chiamati ad ogni evento ifup/ifdown e ai quali
vengono passati come variabili globali la Network e la device, cosa che
permette di operare caso-per-caso. Io l'ho usato per ripristinare il
pointopoint nel caso sia la Network GRE ad andare giù. Hotplug è un udev
senza fronzoli.

Per quanto riguarda il firewall adesso diventa business-as-usual.

Per via del client che ho scelto (AP dell'HPCC) mi sono accorto di
potenziali problemi in caso di rotte statiche in OpenWRT. Volevo
impostare come gw il tunnel GRE, e questo mi ha richiesto di inserire
come rotte statiche (Network > Static Routes) tutte le reti diverse da
Internet che avevano il precedente default gw in comune, tra cui le reti
Ninux.
A far così però, ad ogni riavvio il router rimaneva senza default route,
sebbene io avessi un gw specificato nell'interfaccia GRE. Credevo fosse
un problema derivante dal fatto che è un interfaccia "aliena" per UCI,
visto che se il default gw lo impostavo su una qualsiasi altra
interfaccia lui aggiungeva correttamente la default route in accordo.
Dopo un po' però ha preso a funzionare correttamente, e non sono più
riuscito a riprodurre il problema. Se si ripresenta si può ovviare
sempre grazie ad /etc/hotplug.d/iface/90-gre, ma ho decommentato quelle
righe per ora, anche perché non dovrebbe essere un problema tipico di un
Ground Router Ninux.

Avrei voluto fare in modo che chi si collegasse dal lato hackerspace
dell'HPCC navigasse attraverso il GRE (con beneplacito di Spax), mentre
il resto dell'HPCC attraverso la normale connessione GARR, ma questo
richiede uno sbordellamento con i tag VLAN su AP/Firewall e oltre a non
avere il tempo non è funzionale al test.
In questo momento il traffico che *origina* dal router passa attraverso
il tunnel. Chi volesse testare il tunnel deve mettersi 10.87.1.2 come
default route. Ho provato a darla con un DHCP sull'AP con apposito range
220-250, ma anche se il primo DHCP server sulla strada del caso è l'841,
il "winner" della DHCP-REQUEST rimane sempre 10.87.1.1! Non ho trovato
altra spiegazione se non che anche un vecchio athlon brucia sul tempo il
SoC dell'841 :).

TODO: Mandarlo in test sul ground router ninux-kit ex-edizioni master.
TODO: Il GRE multipoint sui Cisco c'è. Possibile non si possa su Linux?
Investigare.
TODO: Alzare un po' la sicurezza/asticella con qualche regola di firewall?
TODO: Carinizzare gli hotplug, non sono un mago di bash.

È tutto sul GRE,
per ora,
da me.

Stefanauss

-------------- parte successiva --------------
Un allegato non testuale è stato rimosso....
Nome:        signature.asc
Tipo:        application/pgp-signature
Dimensione:  819 bytes
Descrizione: OpenPGP digital signature
URL:         <http://ml.ninux.org/pipermail/calabria/attachments/20140606/e2369b26/attachment-0001.sig>


Maggiori informazioni sulla lista Calabria