Mes travaux perso relatifs à Tetaneutral¶
Auteur : Id2ndR
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
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
4G¶
Inspiré de http://wiki.openwrt.org/doc/howto/usb.tethering
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)
Dans Luci, Network > Interfaces : créer une interface nommée 4G exploitant l'interface usb0, en client dhcp
Pinguer depuis le routeur.
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 :
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
- Installation du client :
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
- 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)
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)
- 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
- 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é.
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
Routage¶
- Configurer l'interface ethernet en hotplug, avec une IP fixe; et l'usb en dhcp (Internet)
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
- 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
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
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.
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
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
- Contenu de /home/id2ndr/scripts/4G_direct_FreeMobile.sh :
#!/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
- Ajout de
post-up /home/id2ndr/scripts/4G_direct_FreeMobile.sh
dans /etc/network/interfaces pour eth0
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).
- 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
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>
- 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
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};" > /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 static\n }\n}" > /etc/ndppd.conf # static permet de répondre à toutes les requêtes : permet de résoudre les éventuels problèmes de transmission de paquet sur le Lan/wifi, et permet également à l'Odroid l'accès au réseau global IPv6 grace à son IP construite sur l'interface eth0.
- ./ndppd -d # A intégrer dans le tinc-up
- Serveur :
- É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 : ok (uniquement si le proxy NDP est réglé sur "static", car sinon il ne fait que relayer les requêtes arrivant sur l'interface eth0)
- ping6 sur id2ndr.tetaneutral.net depuis un PC : OK
- wget -6 google.fr