EdgeRouter 4

J’ai enfin eu la fibre ! après avoir bataillé avec notre syndic et la mairie pour pousser SFR à fibrer l’immeuble pendant plusieurs année ! On pourra dire que SFR a pris son temps. Me voilà donc avec une offre fibre à 1GB/s descendant et 200MB/s montant et un APU, mon ancien routeur, aux abois. En effet un speed test avec la box opérateur me donne un débit réel (mais non-garanti) de 830MB/s descendant, 260MB/s montant et un ping à 10ms, c’est un résultat très honorable par rapport à l’offre commerciale. Avec l’APU en revanche il m’est plus que difficile de dépasser le 300MB/s en descendant, ce qui se voit assez bien avec un htop montrant que le CPU est complètement à genou.

J’ai du coup craqué sur un EdgeRouter 4 de chez Ubiquiti pour remplacer mon APU et bien évidemment laisser la box SFR au placard. Uniquiti propose des produits que je trouve assez intéressant :

  • la cible sont les professionnels et éventuellement les particuliers bidouilleurs dont je fais parti
  • le matériel contient des circuit dédiés permettant de décharger le processeur des opérations réseaux, DPI et IPSec
  • la consommation est très faible : seulement 13W sur ce modèle
  • le logiciel est ouvert à la modification (dans le sens : il peut faire bien plus que ce qu’à prévu initialement le fabricant)
  • il est doté d’un port console pour pouvoir réparer le boitier même quand on a tout cassé
  • la partie logicielle repose entièrement sur une stack Debian, sur lequel Ubiquiti a rajouté une interface web et en ligne de commande pour piloter le boitier.
  • le prix est plus que raisonnable au vu de la qualité du matériel et de l’efficacité

EdgeRouter ou APU ?

Honnêtement c’est un petit bijou. Initialement j’avais pris une carte APU pour être au commande de tout. Le EdgeRouter respecte cela en tout point :

  • on peut rajouter ou enlever des daemons
  • eventuellement il est possible de compiler un logiciel et le faire exécuter par le EdgeRouter, en gardant à l’esprit que le CPU n’est pas non plus un i7 dernier cri
  • tous les services sont open-source, la partie propre à EdgeRouter étant la couche de gestion. Ainsi on retrouve dhcpd, dnsmasq, openssh, iptables, ipsec, radvd, strongswan, python, ddclient, dhclient, le kernel linux, busybox, monit, ntpd…
  • les backups sont totalement consistentes avec la CLI

Je me retrouve donc avec un système opérationnel robuste et plus simple à gérer et sur lequel je ne suis pas limité autrement que par les capacités matérielles.

J’ai listé dans le dernier paragraphes les articles qui m’ont aidé à modifier le router selon mon goûts et vais détaillé comment fonctionne un routeur Ubiquiti.

Les fondations du EdgeRouter

Comme je l’ai indiqué en introduction, le routeur repose sur une base totalement open-source :

root@ubnt /config # cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 7 (wheezy)"
NAME="Debian GNU/Linux"
VERSION_ID="7"
VERSION="7 (wheezy)"
ID=debian
ANSI_COLOR="1;31"
HOME_URL="http://www.debian.org/"
SUPPORT_URL="http://www.debian.org/support/"
BUG_REPORT_URL="http://bugs.debian.org/"

Pour être plus précis, l’OS en question est EdgeOS, qui est un fork de Vyatta, lui-même basé sur Debian.

Pour des soucis d’efficacité énergétique, le CPU utilisé, un quad-core, repose sur une architecture mips64 (tout, mips ou arm, sera plus efficient que l’archi x86/amd64) :

root@ubnt /config # cat /proc/cpuinfo
system type             : UBNT_E300
machine                 : Unknown
processor               : 0
cpu model               : Cavium Octeon III V0.2  FPU V0.0
BogoMIPS                : 2000.00
wait instruction        : yes
microsecond timers      : yes
tlb_entries             : 256
extra interrupt vector  : yes
hardware watchpoint     : yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
isa                     : mips1 mips2 mips3 mips4 mips5 mips64r2
ASEs implemented        : vz
shadow register sets    : 1
kscratch registers      : 4
core                    : 0
VCED exceptions         : not available
VCEI exceptions         : not available

il existe quelques modules propriétaires (du moins, je n’ai pas réussi à trouver où étaient les codes sources) permettant de faire appels aux différents circuits d’accélération matérielle :

root@ubnt /config # lsmod
[...]
cvm_ipsec_kame         38319  0
ipv6                  381814  71 sit,ip6table_mangle,nf_defrag_ipv6,cvm_ipsec_kame,xfrm6_mode_tunnel,nf_conntrack_ipv6
imq                     6736  0
cavium_ip_offload     176733  0
ubnt_nf_app            10668  1 cavium_ip_offload
tdts                  572293  2 cavium_ip_offload,ubnt_nf_app
octeon_rng              1890  0
rng_core                4168  2 octeon_rng
ubnt_platform        2528991  0

La surcouche Ubiquiti

Le EdgeRouter peut se gérer de 4 manières différentes :

  • par l’interface web
  • par l’interface en ligne de commande (CLI)
  • directement en ssh comme dans toute distribution Linux, avec le risque de voir ses changements écrasés par la configuration de l’interface web/cli ou par un reboot
  • grâce à /config

L’interface web est assez limitée en comparaison de la CLI mais pourra convenir à un usage très simple ou très standard. Personnellement je la trouve trop limitée ce qui la rend un peu inutile à mon goût si ce n’est voir visuellement le traffic en temps réel et la santé générale du système.

Dashboard EdgeRouter
Dashboard EdgeRouter

La CLI

La ligne de commande est accessible soit via l’interface Web (en haut à droite), soit via SSH, que je trouve de loin plus pratique à une émulation de console à travers une page web.

Il existe 3 modes à la CLI :

  • les commandes bash habituelles
  • show, permettant de consulter différentes informations au runtime
  • configure, permettant d’accéder à la configuration du routeur

Il est inutile que je détaille le premier mode, il s’agit juste de bash. Exactement il s’agit de vbash, pour lequel l’auto-complétion des fichiers et dossiers ne fonctionnent pas. Sans chercher plus loin, un sudo su me permet de retrouver un bash « normal ». Les deux autres modes en revanches sont la spécificité de EdgeOS et sont assez facile à prendre en main. En effet elles sont dotées de l’auto-complétion : un simple TAB-TAB permet d’afficher les sous-commandes possibles.

show Show

Chow chow

La commande show permet de récupérer un certain nombre d’informations sur le routeur à travers une interface unifiée (un truc complètement raté dans le monde de l’open-source) :

veovis@ubnt ~ $ show<TAB><TAB>
arp                  cspf                 firewall             interfaces           login                queueing             system               upnp2
bfd                  date                 flow-accounting      ip                   mpls                 reboot               tech-support         users
bgp                  debugging            flow-accounting-ipt  ipv6                 nat                  route-map            traffic-control      version
bi-lsp               dhcp                 hardware             ldp                  ntp                  rsvp                 ubnt                 vpls
bridge               dhcpv6               history              lldp                 openvpn              shutdown             udapi                vpn
configuration        dhcpv6-pd            host                 load-balance         pppoe-client         snmp                 unms                 vrrp
conntrack            dns                  incoming             log                  pppoe-server         ssh-recovery         update               webproxy

veovis@ubnt ~ $ show ubnt<TAB><TAB>
discover         discover-server  offload
veovis@ubnt ~ $ show ubnt <TAB>
Possible completions:
  discover      Show UBNT discovered devices
  discover-server
                Show UBNT discover server state
  offload       Show UBNT offload status


veovis@ubnt ~ $ show ubnt offload

IP offload module   : loaded
IPv4
  forwarding: enabled
  vlan      : disabled
  pppoe     : disabled
  gre       : disabled
IPv6
  forwarding: enabled
  vlan      : disabled
  pppoe     : disabled

IPSec offload module: loaded

Traffic Analysis    :
  export    : enabled
  dpi       : enabled
    version       : 1.354

On peut ainsi explorer facilement tout ce que peux offrir show et les sous-commandes étant relativement explicite, deviner la bonne commande est plutôt aisé.

configure

De manière similaire à la commande show, le mode configure est aussi doté de la même d’auto-complétion. On rentre dans ce mode simplement en exécutant configure.

On peut alors

  • show: consulter tout ou partie de la configuration
  • set: modifier un paramètre
  • commit: appliquer les changements effectués de manière non-persistante (perdu au prochain redémarrage)
  • save: persister la configuration
  • edit: peut être vu comme une sorte de « cd subSection »
  • exit: remonter d’un cran (aka « cd .. ») ou quitter le mode configure si l’on est déjà au top-level

Ci-dessous un exemple mettant en évidence la commande edit, laquelle permet d’utiliser show ou set sans devoir spécifier le chemin du paramètre entier, edit permettant de changer de contexte ou de descendre dans l’arborescence. Ainsi plutôt que d’avoir à taper show interfaces ethernet eth2 , le edit interfaces  me permet de ne taper que show ethernet eth2 pour avec le même résultat.

veovis@ubnt# show interfaces ethernet eth2
 address dhcp
 description wan0
 dhcp-options {
     client-option "send vendor-class-identifier &quot;neufbox_NB6VAC-FXC-r0_NB6VAC-MAIN-R4.0.35_NB6VAC-XDSL-A2pv6F039p&quot;;"
     default-route update
     default-route-distance 210
     name-server update
 }
 duplex auto
 firewall {
     local {
         name WAN_LOCAL
     }
 }
 speed auto
[edit]
veovis@ubnt# edit interfaces
[edit interfaces]
veovis@ubnt# show ethernet eth2
 address dhcp
 description wan0
 dhcp-options {
     client-option "send vendor-class-identifier &quot;neufbox_NB6VAC-FXC-r0_NB6VAC-MAIN-R4.0.35_NB6VAC-XDSL-A2pv6F039p&quot;;"
     default-route update
     default-route-distance 210
     name-server update
 }
 duplex auto
 firewall {
     local {
         name WAN_LOCAL
     }
 }
 speed auto
[edit interfaces]
veovis@ubnt# exit
[edit]
veovis@ubnt#

Ubiquiti a fait preuve d’ingéniosité en concevant le fichier de configuration se trouvant dans /config/config.boot . Il s’agit d’un fichier texte lisible dans un format similaire à du JSON. On remarque que ce fichier respecte la même hiérarchie que le mode configure. Par cette simple idée, s’approprier la logique du mode configure devient un vrai jeu d’enfant. Il s’agit aussi du config tree que l’on trouve dans l’interface web.

/config

Dernier petit bijou, le dossier /config . Contrairement au reste, le contenu de ce dossier sera préservé à travers une mise à jour du firmware. Grosso-modo, toutes nos bidouilles doivent se trouver ici.

root@ubnt /home/veovis # ls -lh /config/
total 44
drwxrwsr-x    3 root     vyattacf    4.0K May 21 17:52 auth
-rw-rw-r--    1 root     vyattacf   15.8K Jul  7 14:58 config.boot
-rw-r--r--    1 root     vyattacf    2.0K Jul 29 15:17 dhcpd.leases
drwxrwsr-x    4 root     vyattacf    4.0K May 21 17:05 scripts
drwxrwsr-x    2 root     vyattacf    4.0K Apr 26 20:09 support
drwxr-xr-x    2 root     root        4.0K Apr 26 19:25 udapi-bridge
drwxr-sr-x    3 root     vyattacf      33 Jun 22 19:30 url-filtering
drwxrwsr-x    5 root     vyattacf    4.0K May 28 20:33 user-data
drwxr-sr-x    3 www-data vyattacf    4.0K May 21 15:45 wizard

On va y trouver :

  • le fichier de configuration /config/config.boot
  • les scripts de post-initialization dans /config/scripts/post-config.d/
  • les autres fichiers à garder dans /config/user-data/

Les scripts initialisation m’ont servi entre autres à :

  • ajouter des paquets supplémentaire (nsd3, htop, screen, unbound)
  • remplacer dnsmasq par unbound
  • ajouter des daemons supplémentaires
  • configurer unbound et autres en copiant /config/user-data/root/ dans /

Script me permettant d’installer des paquets supplémentaires :

#!/bin/bash

packages='screen unbound nsd htop'
doneit='/var/lib/my_packages'

if [ -e $doneit ]; then
        exit 0
fi

mount -t tmpfs -o size=30% tmpfs /var/lib/apt/lists
if [ $? != 0 ]; then
        echo Could not mount tmpfs on /var/lib/apt/lists
        exit 1
fi

apt-get update
apt-get --no-install-recommends install -y $packages

if [ $? == 0 ]; then
        echo Package install successful
        touch $doneit
else
        echo Package install failed
fi

umount /var/lib/apt/lists
exit 0

Script permettant la fusion de /config/user-data/root/ dans / et effectuant d’autres opérations spécifiques :

#!/bin/bash

# to be stored into /config/scripts/post-config.d/10_restore-custom.sh
config_root=/config/user-data/root/

# custom PS1
sed -i -e 's/^PS1=.*$/PS1='"'"'\\[\\033[01;32m\\]\\u@\\h\\[\\033[01;34m\\] \\w \\$\\[\\033[00m\\] '"'"'/' /etc/bash.bashrc

# disable ipv6 on eth2 because I do not use the tunnel from sfr
# echo 1 > /proc/sys/net/ipv6/conf/eth2/disable_ipv6

# synchronize the config tree with root
if [ ! -d "$config_root" ]; then
        echo "Nothing to sync"
        exit 0
fi

find "$config_root" \( -type f -o -type l \) -print | \
        while read i;
        do
                target=$(echo $i | cut -d'/' -f5-)
                dir=$(dirname /"$target")
                mkdir -p "$dir"
                cp "$i" "/$target"
        done

# specific tasks for ipsec
ipsec rereadall

# specific tasks for unbound
curl "https://pgl.yoyo.org/adservers/serverlist.php?hostformat=unbound&showintro=1&mimetype=plaintext" > /etc/unbound/local-blocking-data.conf
systemctl enable unbound
systemctl restart unbound

if [ ! -d /var/run/nsd3 ]; then
        install -d -o nsd -g nsd -m 755 /var/run/nsd3
fi

systemctl enable nsd
systemctl restart nsd

curl "https://pgl.yoyo.org/adservers/iplist.php?ipformat=iptables&showintro=1&mimetype=plaintext" | sed 's/OUTPUT/OUT_ADBLOCK/g' > /tmp/iptables.sh
#iptables -N OUT_ADBLOCK
#iptables -F OUT_ADBLOCK
#chmod +x /tmp/iptables.sh
#/tmp/iptables.sh
rm /tmp/iptables.sh
#iptables -D OUTPUT -o eth2 -p tcp -m multiport --dports 80,443 -j OUT_ADBLOCK
#iptables -A OUTPUT -o eth2 -p tcp -m multiport --dports 80,443 -j OUT_ADBLOCK

Mot de la fin

J’espère que cette introduction facilitera votre prise en main. Personnellement j’étais un peu frileux à l’idée de prendre du matos semi-propriétaire mais je suis au final extrêmement satisfait de cet investissement et je ne peux que le recommander pour toute personne ne souhaitant pas avoir un équipement étranger (la box opérateur) dans son réseau local. En bon passionné que je suis, j’attends avec impatience une nouvelle version majeure du firmware qui nous emmènerais sur un kernel 4.x, le kernel 3.10 actuellement utilisé n’étant plus supporté. J’ai lu que la principale difficulté provenant du constructeur CPU qui rechignerait à fournir un SDK compatible avec une version récente de Linux.

Source