sitio personal de Rodrigo Garcia.

Probando bmx7


permalink.

Actualizado - 03 March 2018

categorías: #software #tutoriales #redes_libres

En este post compartiré unas pruebas y pequeña guía del protocolo de enrutamiento Bmx7 para una red en malla.

Para construir una red en malla autónoma hace falta uno o más protocolo de enrutamiento, donde cada nodo en la red se hace descubrir, descubre a otros nodos, avisa a sus vecinos a quienes ha descubierto y también ayuda a llevar información de un nodo a otro a través de el mismo.

Existen varios protocolos de enrutamiento para redes mesh como Batman-adv, Babel, OLSR, bmx6, etc. y en el proyecto LaOtraRed hemos estado probando varios y buscando el protocolo que más se ajuste a las necesidades de una red libre comunitaria y de control colectivo. En ese afán hemos estado trabajando sobre una primera versión estable o 1VE donde hemos definido el protocolo bmx7 como el principal.

Sobre bmx7

Este protocolo es una versión más segura de bmx6. Bmx6 siendo una modificación de Batman-adv, está enfocado a redes en malla (que es lo mismo que decir redes mesh) pero le agrega soporte para IPv6, mejora la difusión del estado de cada nodo, etc [1] .

Bmx7 además le agrega seguridad usando SEMTOR lo que hace que los anuncios de rutas estén firmados criptográficamente [2] .

A pesar de lo complejo que se ve el protocolo, configurar enrutadores para que lo utilicen es sencillo una vez se consigue poner el software necesario en el equipo.

Preparando el escenario

Escenario de prueba

Son básicamente dos nodos, el nodo A y el nodo B se descubren y establecen comunicación con la ayuda de bmx7. El nodo A tiene la dirección IPv6: fa99:1:a::a y también IPv4: 10.64.1.1, de manera similar el nodo B tiene sus propias direcciones IP.

En el escenario descrito A y B anuncian también bloques de red, por ejemplo A dirá que es acreedor del bloque IPv6 fa99:1:a::/48 directamente y también anuncia un bloque IPv4: 10.64.1.1/24 a través de un túnel, la manera de hacer anuncios varía en bmx7 y veremos eso más adelante.

La idea de este escenario es que se puede hacer que un nodo le diga a toda la red y más específicamente a sus vecinos, que tiene conexión a un grupo de direcciones IP (bloque IP) y que a través de si mismo los demás nodos de la red pueden conectarse a los dispositivos sean cuales fueren dentro de los bloques que anuncia.

Preparando los nodos

Vamos a configurar paso a paso ambos enrutadores, para esta prueba he usado dos modelos de enrutadores baratos, el TP-link mr3040 y mr3020.

Normalmente bastaría con descargar la última versión estable del sistema operativo openwrt o lede para estos enrutadores desde https://downloads.lede-project.org/releases/17.01.4/targets/ar71xx/generic/ y buscando las imagenes .factory.bin o .sysupgrade.bin para el mr3020 y 3040 respectivamente. Luego instalar los paquetes necesarios con:

opkg install bmx7 libmbedtls bmx7 bmx7-uci-config \
bmx7-iwinfo bmx7-tun bmx7-table kmod-iptunnel6 \
kmod-ip6-tunnel kmod-iptunnel4 kmod-iptunnel

Las imágenes de firmware por defecto en el repositorio de paquetes de lede u openwrt vienen con la interfaz luci para administrar el enrutador.

Debido a que bmx7 usa criptografía para firmar paquetes y verificar autenticidad, requiere la biblioteca mbedtls instalada en el sistema, como los enrutadores mr3020 y 3040 sólo tienen 4MB de memoria FLASH, si se incluye el luci no hay cabida para bmx7. En modelos de enrtuadores con 8 MB de FLASH no se tiene esta limitación.

Una solución sería desinstalar completamente luci pero no he encontrado una forma sencilla de hacerlo, por lo que se puede construir imágenes de firmware usando buildroot o image-generator, en el post construir imágenes de firmware para enrutadores con build root puedes ver cómo hacerlo.

Por ejemplo usando el image-generator se puede construir imágenes de firmware sin luci y con las dependencias necesarias para bmx7 con:

make image PACKAGES="-libiwinfo-lua -liblua -libubus-lua -libuci-lua \
-lua -luci -luci-app-firewall -luci-base -luci-lib-ip -luci-lib-nixio\
-luci-mod-admin-full -luci-proto-ipv6 -luci-proto-ppp \
-luci-theme-bootstrap -uhttpd -uhttpd-mod-ubus \
bmx7 bmx7-iwinfo kmod-ip6-tunnel kmod-iptunnel6 kmod-iptunnel4 \
kmod-iptunnel bmx7-json bmx7-sms bmx7-table bmx7-topology bmx7-tun\
bmx7-uci-config libmbedtls"

--> También puedes descargar las imágenes de firmware con estas características de mi repositorio de imágenes de firmware de openwrt (este repositorio cambia y no esta garantizado que siempre vaya a funcionar):

Luego instalar las imágenes de firmware correspondientes en los enrutadores. Si nunca lo has hecho revisa esta guía.

Configurando interfaces de red y WiFi

Primero el archivo de interfaces de red para el Nodo A.

/etc/network/interfaces

config interface 'loopback'
    option ifname 'lo'
    option proto 'static'
    option ipaddr '127.0.0.1'
    option netmask '255.0.0.0'

config globals 'globals'
    # mejor no cambiar esto en el enrutador
    option ula_prefix 'fd91:9cd6:f633::/48'

config interface 'lan'
    option proto 'static'
    option type 'bridge'
    option ipaddr '10.64.1.1'
    option netmask '255.255.255.0'
    option ifname 'eth0'

config interface 'mesh'
    option proto 'static'
    option ip6addr 'fa99:1:a::a'

Con lo anterior configuramos dos interfaces, lan en IPv4 y mesh en IPv6.

/etc/config/wireless

config wifi-device 'radio0'
    option type 'mac80211'
    option hwmode '11g'
    option path 'platform/ar933x_wmac'
    option htmode 'HT20'
    option channel '2'
    option country 'BO'
    option txpower '18'
    option disabled '0'

config wifi-iface
    option device 'radio0'
    option network 'mesh'
    option mode 'adhoc'
    option ssid 'bmx7.pruebas'
    option bssid 'D0:D0:11:11:11:11'
    option encryption 'none'

Hacemos que el nodo emita una señal wifi en modo adhoc que con ssid "bmx7.pruebas" y ligada a la interfaz "mesh" definida anteriormente.

/etc/config/bmx7

# modificamos un poco el archivo de configuracion por defecto
# en bmx7
config 'bmx7' 'general'
# usando la interfaz mesh
config 'dev' 'mesh'
        option 'dev' 'wlan0'

# anuncios UHNA (para ipv6 directo)
config 'unicastHna' 'miPrefijoDeRed'
    option 'unicastHna' 'fa99:1:a::/48'

# tuneles (para bloques ipv4)
# anunciar tunel ipv4
config 'tunDev' defaultbmx7
    option 'tunDev' 'defaultbmx7'
    option 'tun4Address' '10.64.1.0/24'
# aceptar anuncios 
config 'tunOut'
    option 'tunOut' 'ip4'
    option 'network' '10.64.0.0/16'

# lo siguiente es para habilitar el plugin bmx7-tun
# y con esto poder crear tuneles 
config 'plugin'
        option 'plugin' 'bmx7_tun.so'

config 'plugin'
        option 'plugin' 'bmx7_table.so'

En la configuración de bmx7, primero definimos en que interfaz va a trabjar el protocolo.

Luego definimos anuncios uHNA que son mensajes que anuncian a los nodos vecinos bloques y direcciones IP que tiene un nodo en la red. Lo bueno de usar UHNAs es que se garantiza que ningún otro nodo pueda utilizar las IP que anuncia un nodo mediante un identificador único y que los bloques de direcciones no se solapen. Todos estos paquetes se asocian a un indentificador único por cada nodo y van firmados criptográficamente.

Finalmente, bmx7 es sólo IPv6 y para anunciar bloques IPv4 utiliza anuncios de túneles. Afortunadamente no tenemos que crear los túneles manualemente ya que bmx7 los crea por nosotros, sólo indicamos mediante tun4Address que este nodo anuncia la red 10.64.1.0/24 y mediante tunOut le decimos que acepte anuncios que estén dentro de 10.64.0.0/16 y que los retransmita.

En el nodo B las configuraciones son similares donde sólo cambian los bloques y direcciones IP correspondientes, si habría otro nodo C o otros más se hace de la misma forma.

Una vez guardadas estas configuraciones, reiniciamos el demonio bmx7 con:

/etc/init.d/network restart
/etc/init.d/bmx7 restart

Haciendo pruebas

El demonio bmx7 se puede consultar en cualquier momento para consultar su estado ,nodos asociados o túneles, a continuación algunas consultas hechas en el enrutador.

bmx7 -c status
# que responde
STATUS:
shortId  name     nodeKey cv revision primaryIp                               tun6Address tun4Address   uptime cpu txQ  nbs rts nodes 
1A0165FA openwrt RSA2048 21 0a82c7c  fd70:1a01:65fa:6d39:dce1:20b6:1299:1f82 ::/0        172.24.3.1/24 0:00:38:28 0.4 0/50 1   1   2/2

# se puede tambien consultar mas detalles
bmx7 -c status originators

# que responde
STATUS:
shortId  name     nodeKey cv revision primaryIp                               tun6Address tun4Address   uptime cpu txQ  nbs rts nodes 
1A0165FA openwrt RSA2048 21 0a82c7c  fd70:1a01:65fa:6d39:dce1:20b6:1299:1f82 ::/0        10.64.0.0/24 0:00:38:28 0.4 0/50 1   1   2/2
ORIGINATORS:
shortId  name     as S s T t descSqn lastDesc descSize cv revision primaryIp                               dev   nbShortId nbName metric hops ogmSqn lastRef 
7B037847 openwrt1   nA A A A A 512     2303     671+747  21 0a82c7c  fd70:7b03:7847:472a:414:9eee:2d98:3e14  wlan0 7B037847  openwrt1 22399K 1    356    0       
1A0165FA openwrt nQ A A A A 413     132         671+749  21 0a82c7c  fd70:1a01:65fa:6d39:dce1:20b6:1299:1f82 ---   ---       ---    257G   0    20     5
# en la salida anterior el nodo B se reconoce como openwrt1
# con identificador 7B037847

# tambien una descripcion mas completa con los detalles de los anuncios de cada nodo
bmx7 -c status originators descriptions tunnels
# que produce una salida muy larga

La guía completa de comandos se puede ver en https://github.com/bmx-routing/bmx7 o una descripcion mas corta con bmx7 --verboseHelp.

Como en las consultas anteriores vemos que el nodo B se ha dectectado, comprobamos que en el enrutador se hayan establecido rutas hacia él, por ejmplo con:

ip -6 route
# que muestra entre su salida que hay una ruta establecida hacia el nodo B
fa99:1:b::/48 via fe80::ea94:f6ff:fe6b:80fa dev wlan0  metric 1024 
fd70:7b03:7847:472a:414:9eee:2d98:3e14 via fe80::ea94:f6ff:fe6b:80fa dev wlan0  metric 1024 
unreachable default dev lo  metric -1  error -128
fa99:1:a::a dev wlan0  metric 256

En bmx7 los nodos configuran automáticamente una dirección IPv6 al azar y un indentificador único en la red, pero los anuncios de redes UHNA son únicos y eso suprime el riesgo de IP spoofing.

Ahora la comunicación entre el nodo A,B o una cantidad arbitraria de nodos es posible, podemos comprobar haciendo por ejemplo la prueba trazando rutas.

traceroute -6 fa99:1:b::b

Que muestra que se puede llegar a esa direccion IP iendo por el nodo B.

traceroute to fa99:1:b::b (fa99:1:b::b), 30 hops max, 16 byte packets
1  fa99:1:b::b (fa99:1:b::b)  1.392 ms  1.581 ms  1.329 ms

# usando ip para ver que ruta se sigue para alcanzar una IP
ip route get fa99:1:b::b
fa99:1:b::b from :: via fe80::ea94:f6ff:fe6b:80fa dev wlan0  src fc99:1:a::a  metric 1024

Modificaciones "en caliente"

En bmx7 no es obligatorio utilizar un archivo de configuración para modificar el comportamiento del protocolo. Cuando el demonio bmx7 esta ejecutándose con comandos se puede por ejemplo hacer que se anuncien bloques adicionales mediante UHNA.

bmx7 -c u=fc01:1934:ffed::/64

Que haría que el nodo también anuncie el bloque fc01:1934:ffed::/64, de igual manera se puede hacer que se anuncien túneles, quitarlos, establecer póliticas para aceptar anuncios y distribuirlos, etc. Consulta la guía oficial.

Con toda la flexibilidad que ofrece bmx7 ya tenemos construida una pequeña red en malla :)

Referencias

  1. An evaluation of BMX6 for Community Wireless Networks
  2. Securely-Entrusted Multi-Topology Routing for Community Networks