MLVPN – Aggregation de liens (ADSL, 3G, 4G, etc)

MLVPN

Pour un besoin, il fallait agréger plusieurs liens ensemble pour avoir un plus gros tuyau.

Voici une manière avec MLVPN.

Il faut 2 parties, pour faire fonctionner cette aggrégation.

Dans cet article on utilisera 1 client (RASPBERRY) et 1 serveur (Centos7).

Sur le raspberry, nous avons:

  • eth0 : LAN : 192.168.0.179
  • wlan0 : Clef 3g  : 192.168.8.100
  • wlan1 : Clef 3g : 192.168.1.102

A la fin, nous aurons une nouvelle interface mlvpn0 dans laquelle le traffic sera envoyer entre les 2 liens. c’est une répartition des paquets et non des connexions.

Cela veut dire qu’une seule connexion (ex: un upload d’un gros fichier) sera répartie sur les 2 liens.

Partie SERVER – CENTOS 7

Je n’avais qu’une Kimsufi avec Centos7 dispo pour cette POC, d’ou l’absence de Freebsd mais le concept reste le même.

Avant tout, installer les dépendances:


yum install libsodium-devel.x86_64 -y

yum install libev-devel.x86_64 -y

 

Puis récupérer le code source MLVPN et le compiler


git clone https://github.com/zehome/MLVPN.git

cd MLVPN/

./autogen.sh

./configure

make

make install

mkdir /etc/mlvpn

useradd -s /bin/true mlvpn

 

Créer le fichier de configuration et le script de status


vi /etc/mlvpn/mlvpn0.conf

[general]
statuscommand = "/etc/mlvpn/mlvpn0_updown.sh"
tuntap = "tun"
loglevel = 2
mode = "server"
interface_name = "mlvpn0"
timeout = 30
password = "xxxxxx"
cleartext_data = 1

[wlan0]
bindport = 5080
bindhost = "0.0.0.0"

[wlan1]
bindport = 5081
bindhost = "0.0.0.0"

 

vi /etc/mlvpn/mlvpn0_updown.sh

#!/bin/bash

error=0; trap "error=$((error|1))" ERR
tuntap_intf="$1"
newstatus="$2"
rtun="$3"
[ -z "$newstatus" ] && exit 1
(
if [ "$newstatus" = "tuntap_up" ]; then
 echo "$tuntap_intf setup"
 /sbin/ifconfig $tuntap_intf 10.42.42.1 netmask 255.255.255.252 mtu 1400 up
 # NAT thru our server (eth0 is our output interface on the server)
 # mlvpn0 link
 /sbin/iptables -t nat -A POSTROUTING -o eth0 -s 10.42.42.0/30 -j MASQUERADE
 # LAN 192.168.0.0/24 from "client"
 /sbin/route add -net 192.168.0.0/24 gw 10.42.42.2
 /sbin/iptables -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/24 -j MASQUERADE
elif [ "$newstatus" = "tuntap_down" ]; then
 /sbin/route del -net 192.168.0.0/24 gw 10.42.42.2
 /sbin/iptables -t nat -D POSTROUTING -o eth0 -s 10.42.42.0/30 -j MASQUERADE
 /sbin/iptables -t nat -D POSTROUTING -o eth0 -s 192.168.0.0/24 -j MASQUERADE
fi
) >> /var/log/mlvpn_commands.log 2>&1
exit $errors

 

chmod 700 /etc/mlvpn/mlvpn0_updown.sh; chown mlvpn:root /etc/mlvpn/mlvpn0_updown.sh

 

Il faut aussi modifier le FW pour autoriser le forward du traffic et le traffic entant sur les 2 ports configurés précédemment:


iptables -A POSTROUTING -s 10.42.42.0/30 -o eth0 -j MASQUERADE

iptables -A INPUT -s IP_RASPBERRY/32 -i eth0 -p udp -m udp --dport 5081 -j ACCEPT
iptables -A INPUT -s IP_RASPBERRY/32 -i eth0 -p udp -m udp --dport 5080 -j ACCEPT

iptables-save > /etc/sysconfig/iptables

Démarrer mlvpn

 


mlvpn -v  --user mlvpn -c /etc/mlvpn/mlvpn0.conf

On check les ports sont bien en écoute:


# netstat -nupl |grep ml
udp 0 0 0.0.0.0:5080 0.0.0.0:* 29260/mlvpn: mlvpn@
udp 0 0 0.0.0.0:5081 0.0.0.0:* 29260/mlvpn: mlvpn@

A ce stade, l’interface mlvpn0 est UP:


# ifconfig mlvpn0
mlvpn0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1400
 inet 10.42.42.1 netmask 255.255.255.252 destination 10.42.42.1
 unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC)
 RX packets 975 bytes 62792 (61.3 KiB)
 RX errors 0 dropped 0 overruns 0 frame 0
 TX packets 999 bytes 1342862 (1.2 MiB)
 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

Reste à voir la partie client.

 

PARTIE CLIENT   – RASPBERRY

Il faut installer les dépendances sur le raspberry:

sudo apt-get install build-essential make autoconf libev-dev git

La lib sodium n’étant pas disponible dans les packages debian, il faut la compiler:

wget --no-check-certificate https://download.libsodium.org/libsodium/releases/libsodium-1.0.3.tar.gz
tar -zxvf libsodium-1.0.3.tar.gz
cd libsodium-1.0.3/
./configure
make
make check
sudo make install
ldconfig

Puis compiler mlvpn comme précédemment :

git clone https://github.com/zehome/MLVPN.git
cd MLVPN
./autogen.sh
./configure
make
make install
mkdir /etc/mlvpn
useradd -s /bin/true mlvpn

La configuration réseau du raspberry est:

iface eth0 inet dhcp

auto wlan0
iface wlan0 inet static
address 192.168.8.100
netmask 255.255.255.0
wpa-ssid "xxxxx"
wpa-psk "xxxxxx"

auto wlan1
iface wlan1 inet static
address 192.168.1.102
netmask 255.255.255.0
wpa-ssid "xxxxx"
wpa-psk "xxxxxx"

On obtient cet ifconfig:

wlan0 Link encap:Ethernet HWaddr 80:1f:02:af:24:34
 inet adr:192.168.8.100 Bcast:192.168.8.255 Masque:255.255.255.0
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:3859 errors:0 dropped:2 overruns:0 frame:0
 TX packets:3409 errors:0 dropped:1 overruns:0 carrier:0
 collisions:0 lg file transmission:1000
 RX bytes:1306343 (1.2 MiB) TX bytes:403217 (393.7 KiB)

wlan1 Link encap:Ethernet HWaddr a0:f3:c1:2e:2b:9c
 inet adr:192.168.1.102 Bcast:192.168.1.255 Masque:255.255.255.0
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:6515 errors:0 dropped:33 overruns:0 frame:0
 TX packets:3462 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 lg file transmission:1000
 RX bytes:2092309 (1.9 MiB) TX bytes:412679 (403.0 KiB)

Il faut modifier la table de routage pour forcer le traffic en provenance des réseaux wifi (192.168.8.0/24 et 192.168.1.0/24) à passer par leurs interfaces respectives wlan0 et wlan1.

vi /etc/iproute2/rt_tables

Ajouter á la fin:

101 wlan0
102 wlan1

Ensuite il faut ajouter les tables de routage suivante:

ip route add 192.168.8.0/24 dev wlan0 scope link table wlan0
ip route add default via 192.168.8.1 dev wlan0 table wlan0

ip route add 192.168.1.0/24 dev wlan1 scope link table wlan1
ip route add default via 192.168.1.1 dev wlan1 table wlan1

ip rule add from 192.168.1.0/24 table wlan1
ip rule add from 192.168.8.0/24 table wlan0

On vérifie:

root@raspberrypi:~# ip rule show
0: from all lookup local
32764: from 192.168.8.0/24 lookup wlan0
32765: from 192.168.1.0/24 lookup wlan1
32766: from all lookup main
32767: from all lookup default

root@raspberrypi:~# ip route show
default via 192.168.0.254 dev eth0
188.165.12.106 via 10.42.42.2 dev mlvpn0 scope link
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.179
192.168.1.0/24 dev wlan1 proto kernel scope link src 192.168.1.102
192.168.8.0/24 dev wlan0 proto kernel scope link src 192.168.8.100

On peut tester un ping en forçant la provenance depuis l’ip des clefs 3g:

root@raspberrypi:~# ping www.google.fr -I192.168.8.100
PING www.google.fr (216.58.211.67) from 192.168.8.100 : 56(84) bytes of data.
64 bytes from par03s14-in-f3.1e100.net (216.58.211.67): icmp_req=1 ttl=51 time=116 ms
64 bytes from par03s14-in-f3.1e100.net (216.58.211.67): icmp_req=2 ttl=51 time=139 ms
^C
--- www.google.fr ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms

root@raspberrypi:~# ping www.google.fr -I192.168.1.102
PING www.google.fr (216.58.211.67) from 192.168.1.102 : 56(84) bytes of data.
64 bytes from par03s14-in-f3.1e100.net (216.58.211.67): icmp_req=1 ttl=55 time=28.6 ms
64 bytes from par03s14-in-f3.1e100.net (216.58.211.67): icmp_req=2 ttl=55 time=218 ms
64 bytes from par03s14-in-f3.1e100.net (216.58.211.67): icmp_req=3 ttl=55 time=140 ms
^C
--- www.google.fr ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms

Ca ping bien, on peut continuer.

On créé la config mlvpn:

Ne pas oublier de remplacer IP_SERVER par l’IP de votre serveur.

vi /etc/mlvpn/mlvpn0.conf

[general]
statuscommand = "/etc/mlvpn/mlvpn0_updown.sh"
tuntap = "tun"
loglevel = 4
mode = "client"
protocol = "udp"
interface_name = "mlvpn0"
timeout = 30
password = "xxxxx"
cleartext_data = 1

[wlan0]
bindhost = "192.168.8.100"
remotehost = "IP_SERVER"
remoteport = 5080

[wlan1]
bindhost = "192.168.1.102"
remotehost = "IP_SERVER"
remoteport = 5081

Maintenant on démarre mlvpn:

mlvpn   --user mlvpn -c /etc/mlvpn/mlvpn0.conf

Dans les logs /var/log/syslog:

Aug 21 09:38:07 raspberrypi ifplugd(mlvpn0)[3123]: ifplugd 0.28 initializing.
Aug 21 09:38:07 raspberrypi ifplugd(mlvpn0)[3123]: Using interface mlvpn0/00:00:00:00:00:00 with driver <tun> (version: 1.6)
Aug 21 09:38:07 raspberrypi ifplugd(mlvpn0)[3123]: Using detection mode: SIOCETHTOOL
Aug 21 09:38:07 raspberrypi ifplugd(mlvpn0)[3123]: Initialization complete, link beat detected.
Aug 21 09:38:07 raspberrypi ifplugd(mlvpn0)[3123]: Executing '/etc/ifplugd/ifplugd.action mlvpn0 up'.
Aug 21 09:38:07 raspberrypi ifplugd(mlvpn0)[3123]: client: Ignoring unknown interface mlvpn0=mlvpn0.
Aug 21 09:38:07 raspberrypi ifplugd(mlvpn0)[3123]: Program executed successfully.

Le tunnel doit être up:

root@raspberrypi:~# ifconfig mlvpn0
mlvpn0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
 inet adr:10.42.42.2 P-t-P:10.42.42.2 Masque:255.255.255.252
 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1400 Metric:1
 RX packets:999 errors:0 dropped:0 overruns:0 frame:0
 TX packets:976 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 lg file transmission:500
 RX bytes:1342862 (1.2 MiB) TX bytes:62844 (61.3 KiB)

On ping l’autre bout du tunnel:

root@raspberrypi:~# ping 10.42.42.1
PING 10.42.42.1 (10.42.42.1) 56(84) bytes of data.
64 bytes from 10.42.42.1: icmp_req=1 ttl=64 time=288 ms
64 bytes from 10.42.42.1: icmp_req=2 ttl=64 time=193 ms
64 bytes from 10.42.42.1: icmp_req=3 ttl=64 time=133 ms
^C
--- 10.42.42.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 133.227/205.107/288.171/63.750 ms

Nous avons aussi de nouvelles routes pour l’interface mlvpn0:

root@raspberrypi:~# ip route show
default via 192.168.0.254 dev eth0
10.42.42.0/30 dev mlvpn0 proto kernel scope link src 10.42.42.2
188.165.12.106 via 10.42.42.2 dev mlvpn0 scope link
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.179
192.168.1.0/24 dev wlan1 proto kernel scope link src 192.168.1.102
192.168.8.0/24 dev wlan0 proto kernel scope link src 192.168.8.100

Pour forcer du traffic passant par ce nouveau tunnel, il faudra créér une route :

root@raspberrypi:~# ip route add 8.8.8.8 via 10.42.42.2

root@raspberrypi:~# traceroute -I 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1 10.42.42.1 (10.42.42.1) 135.070 ms * *
 2 * * *
 3 gra-g2-a9.fr.eu (178.33.103.227) 134.922 ms * *
 4 * * *

root@raspberrypi:~# dig +short @8.8.8.8 www.test.com
69.172.200.235

root@raspberrypi:~# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_req=1 ttl=58 time=250 ms
64 bytes from 8.8.8.8: icmp_req=2 ttl=58 time=93.4 ms
64 bytes from 8.8.8.8: icmp_req=3 ttl=58 time=193 ms
64 bytes from 8.8.8.8: icmp_req=4 ttl=58 time=58.7 ms
64 bytes from 8.8.8.8: icmp_req=5 ttl=58 time=64.2 ms

Pour joindre 8.8.8.8, le traceroute indique bien le passage par le tunnel mlvpn0 (10.42.42.1).

Tout est fonctionnel.