Projet

Général

Profil

Id2ndR » Historique » Version 12

Version 11 (Fabien ADAM, 28/01/2016 00:51) → Version 12/13 (Fabien ADAM, 28/01/2016 10:44)

h1. Mes travaux perso relatifs à Tetaneutral

Auteur : Id2ndR

h2. Virtualisation

Au dessus, de libvirt, je fais tourner quelques VM sur ma machine Zbox ID18 http://www.ldlc.com/fiche/PB00158714.html : Celeron double cœurs supportant le VT, avec 8Go de RAM

h2. OpenWRT

Je possède un TP-Link WDR3600 gigabit et double bande N. Il tourne sous Barrier Breaker 14.04.

Objectifs :
- connecter le routeur à Internet via une connexion 4G
- sortir sur une VM tournant sur ma machine à Tetaneutral, pour avoir un accès réseau complet (IP fixe, IPv6, téléphonie SIP, pas de bridage ni de modification du flux via les proxys transparents)
- brancher un téléphone IP ethernet (offre Plug&Phone d'OVH) qui passe dans le VPN, et qui fonctionne normalement sans aucune configuration

h3. 4G

Inspiré de http://wiki.openwrt.org/doc/howto/usb.tethering
<pre>
root@OpenWrt:~# opkg update
root@OpenWrt:~# opkg install kmod-usb-net-rndis
root@OpenWrt:~# insmod usbnet
root@OpenWrt:~# insmod cdc_ether
root@OpenWrt:~# insmod rndis_host
root@OpenWrt:~# ifconfig usb0
usb0 Link encap:Ethernet HWaddr 02:34:68:55:02:03
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
</pre>
Dans Luci, Network > Interfaces : créer une interface nommée 4G exploitant l'interface usb0, en client dhcp

Pinguer depuis le routeur.

h3. OpenVPN

Mise en place :
* Certificat SSL du serveur (VM) : généré par CA-Cert (je n'ai jamais pu faire marcher le VPN sur OpenWRT avec un certificat auto-signé)
* Certificat d'un certificat client : généré avec easy-rsa (build-ca, build-key-server, build-key). Remarque : il n'est pas nécessaire que ces certificats soient issues du certificat du serveur vérifié à la connexion, car le serveur connaît son référentiel de clef, indépendament du certificat serveur présenté sur le port d'écoute.
* Configuration du serveur :
<pre>
id2ndr@id2ndr-vm: ~$ cat /etc/openvpn/id2ndr.conf
##################################
dev tun
proto udp
port 1194

ca /etc/openvpn/easy-rsa/keys/class3.crt
cert /etc/openvpn/easy-rsa/keys/id2ndr.toulan.fr.crt
key /etc/openvpn/easy-rsa/keys/id2ndr.toulan.fr.key
dh /etc/openvpn/easy-rsa/keys/dh1024.pem

user nobody
group nogroup
server 10.9.0.0 255.255.255.0

persist-key
#persist-tun

keepalive 10 100

status /var/log/openvpn-status.log
verb 3
client-to-client

#push "redirect-gateway def1"
#set the dns servers
#push "dhcp-option DNS 8.8.8.8"
#push "dhcp-option DNS 8.8.4.4"
push "redirect-gateway def1"
push dhcp-option DNS 91.224.149.254

log-append /var/log/openvpn
comp-lzo adaptive
</pre>

* Installation du client :
<pre>
root@OpenWrt:~# opkg update; opkg install openvpn-openssl
root@OpenWrt:~# uci set openvpn.custom_config.enabled=1
root@OpenWrt:~# uci commit
root@OpenWrt:~# cat /etc/openvpn/my-vpn.conf
dev tun
client
#proto tcp
proto udp
remote id2ndr.toulan.fr 1195
resolv-retry infinite
nobind
persist-key
persist-tun
ca /etc/openvpn/class3.crt
cert /etc/openvpn/Id2ndR.crt
key /etc/openvpn/Id2ndR.key
comp-lzo no
verb 3
root@OpenWrt:/etc/openvpn# wget http://www.cacert.org/certs/class3.crt
root@OpenWrt:~# vi /etc/openvpn/Id2ndR.crt
root@OpenWrt:~# vi /etc/openvpn/Id2ndR.key
root@OpenWrt:~# uci set openvpn.custom_config.enabled=1
root@OpenWrt:~# uci commit
root@OpenWrt:~# /etc/init.d/openvpn start
root@OpenWrt:~# logread
[..]
Sat Dec 6 19:35:15 2014 daemon.warn openvpn(custom_config)[25584]: WARNING: file '/etc/openvpn/Id2ndR.key' is group or others accessible
Sat Dec 6 19:35:15 2014 daemon.notice netifd: Interface 'wan_vpn' is disabled
Sat Dec 6 19:35:15 2014 daemon.notice openvpn(custom_config)[25584]: Socket Buffers: R=[163840->131072] S=[163840->131072]
Sat Dec 6 19:35:15 2014 daemon.notice openvpn(custom_config)[25584]: UDPv4 link local: [undef]
Sat Dec 6 19:35:15 2014 daemon.notice openvpn(custom_config)[25584]: UDPv4 link remote: [AF_INET]91.224.149.109:1195
Sat Dec 6 19:35:15 2014 daemon.notice openvpn(custom_config)[25584]: TLS: Initial packet from [AF_INET]91.224.149.109:1195, sid=2e0c718b e9ec8be6
Sat Dec 6 19:35:15 2014 daemon.notice openvpn(custom_config)[25584]: VERIFY OK: depth=1, O=CAcert Inc., OU=http://www.CAcert.org, CN=CAcert Class 3 Root
Sat Dec 6 19:35:15 2014 daemon.notice openvpn(custom_config)[25584]: VERIFY OK: depth=0, CN=id2ndr.toulan.fr
Sat Dec 6 19:35:16 2014 daemon.notice openvpn(custom_config)[25584]: Data Channel Encrypt: Cipher 'BF-CBC' initialized with 128 bit key
Sat Dec 6 19:35:16 2014 daemon.notice openvpn(custom_config)[25584]: Data Channel Encrypt: Using 160 bit message hash 'SHA1' for HMAC authentication
Sat Dec 6 19:35:16 2014 daemon.notice openvpn(custom_config)[25584]: Data Channel Decrypt: Cipher 'BF-CBC' initialized with 128 bit key
Sat Dec 6 19:35:16 2014 daemon.notice openvpn(custom_config)[25584]: Data Channel Decrypt: Using 160 bit message hash 'SHA1' for HMAC authentication
Sat Dec 6 19:35:16 2014 daemon.notice openvpn(custom_config)[25584]: Control Channel: TLSv1.0, cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA, 2048 bit RSA
Sat Dec 6 19:35:16 2014 daemon.notice openvpn(custom_config)[25584]: [id2ndr.toulan.fr] Peer Connection Initiated with [AF_INET]91.224.149.109:1195
Sat Dec 6 19:35:18 2014 daemon.notice openvpn(custom_config)[25584]: SENT CONTROL [id2ndr.toulan.fr]: 'PUSH_REQUEST' (status=1)
Sat Dec 6 19:35:18 2014 daemon.notice openvpn(custom_config)[25584]: PUSH: Received control message: 'PUSH_REPLY,redirect-gateway def1,dhcp-option DNS 91.224.149.254,route 10.9.0.0 255.255.255.0,topology net30,ping 30,ping-restart 100,ifconfig 10.9.0.6 10.9.0.5'
Sat Dec 6 19:35:18 2014 daemon.notice openvpn(custom_config)[25584]: OPTIONS IMPORT: timers and/or timeouts modified
Sat Dec 6 19:35:18 2014 daemon.notice openvpn(custom_config)[25584]: OPTIONS IMPORT: --ifconfig/up options modified
Sat Dec 6 19:35:18 2014 daemon.notice openvpn(custom_config)[25584]: OPTIONS IMPORT: route options modified
Sat Dec 6 19:35:18 2014 daemon.notice openvpn(custom_config)[25584]: OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
Sat Dec 6 19:35:18 2014 daemon.notice openvpn(custom_config)[25584]: TUN/TAP device tun0 opened
Sat Dec 6 19:35:18 2014 daemon.notice openvpn(custom_config)[25584]: TUN/TAP TX queue length set to 100
Sat Dec 6 19:35:18 2014 daemon.notice openvpn(custom_config)[25584]: do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0
Sat Dec 6 19:35:18 2014 daemon.notice openvpn(custom_config)[25584]: /sbin/ifconfig tun0 10.9.0.6 pointopoint 10.9.0.5 mtu 1500
Sat Dec 6 19:35:18 2014 daemon.notice openvpn(custom_config)[25584]: /sbin/route add -net 91.224.149.109 netmask 255.255.255.255 gw 192.168.0.1
</pre>

Résultats :
* j'ai mesuré environ 70% d'utilisation CPU sur le routeur pour faire passer 17 méga. Ceci est cohérent avec [[Benchmark_VPN]].
* en 4G, avec une SIM Red, je fais passé en général 6 méga down / 1 méga up (mais parfois beaucoup plus)

h3. Routage

* Nat via le VPN : inspiré de http://wiki.openwrt.org/doc/howto/vpn.server.openvpn.tun Use-Case 3
** Dans Luci, Network > Interfaces : créer une interface nommée wan_vpn exploitant l'interface tun0, en client dhcp
** Dans Luci, Network > Firewall : créer une zone wan_vpn avec l'interface wan_vpn en activant Masquerading
** Dans Luci, Network > Firewall : supprimer la zone lan existante. Créer la zone lan avec le forward vers la zone wan_vpn
** Depuis un PC derrière le routeur : traceroute google.fr doit sortir par h7.tetaneutral.net (4ème nœuds chez moi, à cause de la VM)

Résultats :
* Le VPN ajoute en général 20-25ms par rapport à une route directe (vers un autre site que tetaneutral).
* Le VPN ne réduit pas le débit par rapport à la connexion hors VPN.
* La VoIP (SIP) fonctionne très bien via le VPN

Limites :
* Pour les jeux en ligne, on tourne autour de 100-105ms de ping avec le VPN contre 80ms en connexion direct.
* Pas de sélection des flux à faire passer dans le VPN, et ceux à faire passer directement en 4G :
** Le masquerade d'OpenWRT fait via luci fonctionne par zone, et s'il est possible d'autoriser le forward d'une zone vers plusieurs zones, seule la dernière zone est prise en compte
** Il n'est pas possible via Luci d'utiliser une même zone dans plusieurs règles de forward vers chacun une zone différente
** La table de routage du noyau linux ne permet pas de définir plusieurs passerelles par défaut.

Piste à explorer pour contourner les limites ci-dessus : installer iproute2, et ajouter des étiquettes sur les différents flux, pour faire un routage plus évolué.

h2. Raspberry Pi

Objectifs :
* Transformer le rPi en routeur, avec comme interface de sortie vers Internet un appareil en usb, et comme interface LAN, le port ethernet
* Encapsuler la connexion des clients sur le LAN dans le VPN
* Faire du filtrage pour choisir explicitement quoi router dans le VPN, et quoi faire passer en direct

h3. Routage

* Configurer l'interface ethernet en hotplug, avec une IP fixe; et l'usb en dhcp (Internet)
<pre>
auto eth0
allow-hotplug eth0
iface eth0 inet static
address 192.168.1.1
netmask 255.255.255.0
post-up iptables-restore < /etc/network/iptables

auto usb0
allow-hotplug usb0
iface usb0 inet dhcp
</pre>
* Installer le paquet dnsmasq, et lui donner la page d'IP à allouer en DHCP. dnsmasq fait office de relai DNS de manière automatique, et fourni également la route par défaut (il indique que le rPi fait office de passerelle vers Internet) : echo "dhcp-range=eth0,192.168.1.2,192.168.1.10,4h" | sudo tee /etc/dnsmasq.d/raspberry.conf
* Activer le routage sur le rPi :
** l'ip forward : Décommenter la ligne _net.ipv4.ip_forward=1_ dans /etc/sysctl.conf, et appliquer les modifications avec _sudo sysctl -p /etc/sysctl.conf_ (vérification : sudo sysctl net.ipv4.ip_forward)
** le nat : sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE; sudo iptables-save | sudo tee /etc/network/iptables

h3. OpenVPN

* Installer le paquet openvpn.
* Recopier la conf (4 fichier) dans /etc/openvpn
* Redémarrer le service

TODO : tester 2 connexions VPN en //, pour éventuellement faire du bounding (si FreeMobile limite le débit vers tetaneutral par flux)

TODO : mettre en place de l'IPv6

h3. Routage sélectif

TODO : avec iproute2

Ici le rPi :
* prend le net via la 4G, soit en usb, soit en wifi, cela ne change rien (sauf l'IP de la passerelle utilisée ci-dessous)
* partage le net via son port ethernet, branché sur un switch, en faisant serveur DHCP

Objectif : faire transiter tous les flux dans le VPN, sauf ceux qui ne doivent pas être ralentis (ping ou bridage FreeMobile)
Source : http://irp.nain-t.net/doku.php/100iproute:020_iproute2

Démo : ici on va faire passer le web via la 4G, et le reste dans le VPN.
<pre>
id2ndr@raspberrypi ~ $ sudo vim.tiny /etc/iproute2/rt_tables # Ajout de la ligne "200 4G"
id2ndr@raspberrypi ~ $ sudo ip rule add fwmark 80 table 4G
id2ndr@raspberrypi ~ $ ip rule list
0: from all lookup local
32764: from all fwmark 0x50 lookup 4G
32765: from all fwmark 0x50 lookup 4G
32766: from all lookup main
32767: from all lookup default
id2ndr@raspberrypi ~ $ ip a s dev wlan0
4: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 00:08:a1:ac:cf:ab brd ff:ff:ff:ff:ff:ff
inet 192.168.43.241/24 brd 192.168.43.255 scope global wlan0
valid_lft forever preferred_lft forever
inet6 fe80::208:a1ff:feac:cfab/64 scope link
valid_lft forever preferred_lft forever
id2ndr@raspberrypi ~ $ sudo ip route add default via 192.168.43.1 table 4G
id2ndr@raspberrypi ~ $ ip r s
0.0.0.0/1 via 10.9.0.5 dev tun0
default via 192.168.43.1 dev wlan0
10.9.0.0/24 via 10.9.0.5 dev tun0
10.9.0.5 dev tun0 proto kernel scope link src 10.9.0.6
128.0.0.0/1 via 10.9.0.5 dev tun0
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.1
192.168.43.0/24 dev wlan0 proto kernel scope link src 192.168.43.241
id2ndr@raspberrypi ~ $ ip r s table 4G
default via 192.168.43.1 dev wlan0
id2ndr@raspberrypi ~ $ sudo iptables -t mangle -A PREROUTING -i eth0 -p tcp --dport 80 -j MARK --set-mark 80
</pre>

En activant ou non la règle iptables à la fin, on peut comparer un speedtest passant dans le VPN ou en direct

Tests :
* sudo tcptraceroute google.fr 80 # doit sortir en direct
* sudo tcptraceroute google.fr 100 # doit passer par tetaneutral

Mise en place permanente :
* Contenu de /home/id2ndr/scripts/4G_direct_FreeMobile.sh :
<pre>
#!/bin/bash

sudo ip route add default via 192.168.43.1 table 4G
sudo ip rule add fwmark 80 table 4G
# Web
sudo iptables -t mangle -A PREROUTING -i eth0 -p tcp --dport 80 -j MARK --set-mark 80
# Jeu en ligne (pour le ping) : Steam
sudo iptables -t mangle -A PREROUTING -i eth0 -p udp --dport 27000:27015 -j MARK --set-mark 80
sudo iptables -t mangle -A PREROUTING -i eth0 -p tcp --dport 27030:27039 -j MARK --set-mark 80
</pre>
* Ajout de @ post-up /home/id2ndr/scripts/4G_direct_FreeMobile.sh@ dans /etc/network/interfaces pour eth0

h2. IPv6 et VPN

Les VPN peuvent faire transiter de l'IPv6, mais ce protocole étant assez vaste par nature, le contrôle fait par les VPN pose souvent problème.
Dans mon cas, je n'ai pas réussi à router correctement l'IPv6 au dela du VPN lorsque je spécifiais des sous-réseaux IPv6 dans la conf des VPN (OpenVPN et tinc).

Le plus simple est de ne pas indiquer au VPN qu'il y a de l'IPv6, pour après faire la configuration avec iproute2. Cette solution est d'ailleurs utilisée à TTN pour faire transiter l'IPv6 à travers les ponts wifi.
* Avec OpenVPN, il faut le lancer en ligne de commande avec les options en argument (je n'ai pas réussi à le faire fonctionner avec un fichier de configuration) ; exemple sur le client _sudo openvpn --dev tunipv6 --dev-type tun --lport 0 --proto udp --daemon --remote 91.224.149.109 65002 --secret /etc/openvpn/secret.key --keepalive 10 60 --verb 3 --log-append /tmp/tunipv6.log --mssfix 1389_
* Avec Tinc, il suffit de le faire fonctionner au niveau 2 (ethernet) : _Mode = switch_ dans /etc/tinc/tinc.conf

h3. Routage et configuration automatique

L'idée est d'apporter l'IPv6 aux clients derrière le VPN, qui sont derrière un switch physique.
* Plan réseau : <Internet>---</56 TTN sur le serveur>---VPN---</64 sur le LAN>
* Voici mon architecture matérielle : <Internet>---<Serveur à TTN>---4G---<smartphone>---usb---<Odroid_C1>--eth---<switch_wifi>---<PCs>

Éléments techniques pour le routage :
* Conteneur docker sur le serveur : déclare le sous-réseau en /64 à router dans le VPN
* Pas d'IPv6 global à l'entrée et à la sortie du tunnel VPN : l'utilisation des adresses de liens permettra de pousser le /64 au delà du Odroid_C1 : sur le LAN
* Proxy NDP pour pouvoir router le trafic unicast à travers les liens-locaux

h3. Mise en place

* Tinc :
** Serveur :
*** mkdir /docker_volumes/tinc ; cd /docker_volumes/tinc ; echo -e "Name = tinc_ipv6\nForwarding = kernel\nMode = switch" > tinc.conf ; echo "Address = id2ndr.tetaneutral.net" > hosts/tinc_ipv6 ; echo -e "#!/bin/sh\nip link set $INTERFACE up\nip link set mtu 1400 dev $INTERFACE\nip -6 addr add fe80::81:6d03/64 dev $INTERFACE\nip -6 route add 2a01:6600:8081:6d03::/64 dev $INTERFACE" > tinc-up ; chmod +x tinc-up
*** docker run -d --name tinc --net=host --device=/dev/net/tun --cap-add NET_ADMIN --volume /docker_volumes/tinc:/etc/tinc jenserat/tinc start -D
*** docker exec -ti tinc tinc init # Génère les clefs de l'hôte
*** docker exec -ti tinc tinc export # Récupérer la conf hosts/tinc_ipv6
*** docker restart tinc
** Client :
*** apt install tinc
*** cd /etc/tinc ; echo -e "Name = tinc_ipv6_odroid\nForwarding = kernel\nMode = switch" > tinc.conf ; echo -e "Name = tinc_ipv6_odroid\nInterface=vpn6\nConnectTo = tinc_ipv6" > hosts/tinc_ipv6_odroid ; echo -e "#!/bin/sh\nip link set $INTERFACE up\nip link set mtu 1400 $INTERFACE\nip -6 route add default via fe80::81:6d03 dev $INTERFACE > tinc-up ; chmod +x tinc-up ; echo "Import de hosts/tinc_ipv6"
*** tincd -K # Génère les clefs de l'hôte
*** tincd #
Puis dans docker, on vérifie la connexion avec : tinc dump node
*** apt install radvd # Va indiquer le sous-réseau à utiliser pour les PC sur le LAN
*** echo -e "interface eth0\n{\n AdvSendAdvert on;\n prefix 2a01:6600:8081:6d03::/64\n {\n AdvRouterAddr on; \n };\n RDNSS 2a01:6600:8081:ffff:: {\n };\n};" };\n}; " > /etc/radvd.conf
*** sudo service radvd start
*** echo "Télécharger NDPPD sur https://github.com/DanielAdolfsson/ndppd/releases"
*** make
*** echo -e "proxy vpn6 {\n router yes\n timeout 500 \n ttl 30000\n rule 2a01:6600:8081:6d03::/64 {\n auto\n }\n}" > /etc/ndppd.conf
*** ./ndppd -d # A intégrer dans le tinc-up

Ensuite on teste :
* Écoute du trafic un peu partout : sudo tcpdump ip6 and icmp6 -i vpn6 -n
* ping6 sur l'adresse de lien (odroid vers conteneur) : ping6 fe80::81:6d31%vpn6
* ping6 sur adresse global depuis l'odroid : ko (probablement car le proxy NDP n'agit pas car les demandes n'entrent pas réellement par l'interface eth0
* ping6 sur id2ndr.tetaneutral.net depuis un PC : OK
* wget -6 google.fr