Un moment après avoir posté cette question, j'ai changé certains termes dans mes recherches sur Google et trouvé le bijou suivant d'un article de blog: http://simonmott.co.uk/vpn-bonding
L'article est long et fournit toutes les informations nécessaires pour que cela fonctionne. Cependant, l'approche adoptée par l'auteur présente un défaut important. En tunnelant sur SSH, il effectue le transport par tunnel TCP . Ack. Cela signifie que si vous tunnelisez TCP via le tunnel, vous avez TCP en plus de TCP. Avec toute latence ou perte de paquet significative, les piles TCP deviendront confuses et commenceront à se battre comme tous les deux Les piles TCP tentent de gérer les algorithmes de contrôle d'encombrement, les retransmissions, etc. Cela limite considérablement votre débit, sauf si vous seulement utilisez quelque chose comme UDP dans le tunnel (ce qui signifie que vous ne pouvez pas accéder au Web).
L'article mentionne que cela fonctionnera de manière équivalente avec autre chose que ssh en tant que tunnel, et il a raison . J'ai décidé d'utiliser la fonctionnalité point à point d'OpenVPN pour cela. Ce n'est pas extrêmement sécurisé car il utilise une clé statique, mais la sécurité était suffisante pour mes besoins (seules les menaces persistantes avancées peuvent casser le cryptage).
OpenVPN peut transporter sur TCP ou sur ... UDP ! Nous voulons rendre la couche de transport de notre tunnel UDP, car si les paquets sont perdus, la couche TCP "interne" se chargera du contrôle de la congestion. Et si vous exécutez UDP dans UDP, le code de l’application est responsable de la perte de paquets ou de la latence, et il aura tendance à la gérer correctement.
J'ai rencontré un problème majeur sous la forme d'un régression du noyau Cela a parfois été le cas au cours d’une publication ponctuelle de la série 3.13, et cela n’a pas encore été résolu, même dans git master de torvalds. Ceci n'est pas mentionné dans l'article car la régression n'existait pas au moment de la publication du message. Sur votre client et sur votre serveur, vous devrez soit recompiler votre noyau avec ce patch (Assez simple à appliquer manuellement si patch
refuse de travailler), ou utilise une version du noyau de 3.13.0 ou antérieure.
Pour mes besoins, j’utilisais Debian Wheezy (actuellement Debian). oldstable
branche) avec le noyau 3.2 pour le serveur, car je ne voulais pas recompiler mon noyau sur un VPS Amazon EC2 t2.nano Du côté client (un bureau Linux Mint), je suis allé avec la recompilation du noyau. Donc, les deux méthodes fonctionnent.
Voici les instructions pour le configurer une fois votre noyau recompilé:
Vous allez avoir quatre openvpn
processus: deux sur le client et deux sur le serveur. Utilisez openvpn version 2.1 ou ultérieure, sinon cela ne fonctionnera pas. Placez les fichiers dans le répertoire / etc / openvpn (sauf si vous avez un fichier sysconfdir
et un openvpn compilé sur mesure).
Dans mon cas, j'ai deux cartes d'interface réseau distinctes, eth0
et eth1
sur le serveur, qui fournissent deux adresses IP publiques distinctes, abrégées ci-dessous SERVER_IP1
et SERVER_IP2
. Sur le client, j'ai eth1
et wlan0
connecté à mes liaisons ascendantes Internet et à leurs passerelles (trouvées à l'aide de ifconfig
et route -n
) sont abrégés en GW1
et GW2
.
Créer static.key
, lisez l'OpenVPN page de manuel .
Serveur tun0.conf:
dev tun0
local SERVER_IP1
proto udp
topology p2p
push "topology p2p"
secret static.key
keepalive 30 90
Serveur tun1.conf:
dev tun1
local SERVER_IP2
proto udp
topology p2p
push "topology p2p"
secret static.key
keepalive 30 90
Tun0.conf client:
dev tun0
nobind
remote SERVER_IP1
proto udp
topology p2p
secret static.key
Client tun1.conf:
dev tun1
nobind
remote SERVER_IP2
proto udp
topology p2p
secret static.key
Maintenant, vous voulez démarrer les instances OpenVPN sur le serveur premier , puis le client.
Une fois que tu as tun0
et tun1
tous deux connectés en POINTOPOINT
mode (il faut dire que dans la description de l'interface lors de l'exécution ifconfig
), vous êtes prêt à configurer le lien de liaison, bond0
.
Je suppose que vous utilisez Debian, Ubuntu ou une de leurs fourchettes pour les fichiers de configuration. Vous pouvez effectuer une configuration équivalente sur des systèmes CentOS / RHEL dans /etc/sysconfig/network-scripts/ifcfg-bond0
si je me souviens bien. Vous devrez ajuster la syntaxe de configuration pour cette variante de système d'exploitation. Et les choses pourraient changer considérablement dans un avenir proche avec l'introduction de systemd et de son démon réseau.
Quoi qu'il en soit, ajoutez ceci à /etc/network/interfaces
sur le serveur:
iface bond0 inet static
address 172.26.0.1
netmask 255.255.255.252
bond-slaves tun0 tun1
bond_mode balance-rr
Et sur le client:
iface bond0 inet static
address 172.26.0.2
netmask 255.255.255.252
bond-slaves tun0 tun1
bond_mode balance-rr
Assure-toi ifenslave
est une commande valide sur la ligne de commande avant de continuer. Sinon, installez-le à partir de votre gestionnaire de paquets, avec quelque chose comme: sudo apt-get install ifenslave
.
Assurez-vous également de décommenter la ligne qui dit #net.ipv4.ip_forward=1
dans /etc/sysctl.conf
et vous devrez peut-être echo 1 > /proc/sys/net/ipv4/ip_forward
si vous ne voulez pas redémarrer après avoir changé /etc/sysctl.conf
.
Voici mon script de démarrage pour le client; vous devrez remplacer plusieurs valeurs de réserve (SERVER_IP1, SERVER_IP2, GW1, GW2, eth1
et wlan0
, etc.) pour que cela fonctionne pour vous.
Faire ne pas remplacer 172.26.0.1
/ 172.26.0.2
avec n'importe quoi; Ce sont des adresses IP privées choisies de manière arbitraire qui correspondent respectivement au lien bond0 du serveur et au lien bond0 du client.
#!/bin/bash
modprobe bonding
modprobe tun
iptables -F
#Force connecting to each of the two server IPs through the separate Internet uplinks you have
ip route add SERVER_IP1 via GW1 dev eth1
ip route add SERVER_IP2 via GW2 dev wlan0
#Connect to OpenVPN - this establishes the tunnel interfaces
sleep 1
screen -mdS tun0 openvpn --config /etc/openvpn/tun0.conf
sleep 1
screen -mdS tun1 openvpn --config /etc/openvpn/tun1.conf
sleep 5
#The next line should be all you need, but I find it doesn't work on Linux Mint, it just hangs after partially configuring the interface. Works fine on Debian Wheezy though.
ifup bond0 >& /dev/null &
sleep 5
killall ifup >& /dev/null
ifconfig bond0 up >& /dev/null
#If the ifup script doesn't do its job (it fails on certain Debian OSes depending on the version of your ifenslave program), we have to manually set it up - the next few lines take care of that
ifconfig bond0 172.26.0.2 netmask 255.255.255.252
sleep 2
echo '+tun0' > /sys/class/net/bond0/bonding/slaves
echo '+tun1' > /sys/class/net/bond0/bonding/slaves
#Clear the default gateway and set it to the bond interface
#Required regardless of whether you had to manually configure bond0 above or not
ip route del 0.0.0.0/0
ip route add 0.0.0.0/0 via 172.26.0.1 dev bond0
#Use fair queue controlled delay active queue management for managing multiple TCP flows simultaneously - prevents webpages from loading horribly slowly while you have a download going - requires a recent kernel (3.2 or later should suffice)
tc qdisc add dev bond0 root fq_codel
#DEBUGGING
#On client and server:
#ifconfig bond0, make sure IPs are assigned
#iptables -F on client (don't need any rules)
#cat /sys/class/net/bond0/bonding/slaves - make sure tun0 and tun1 are there
#ifdown bond0; modprobe bonding; ifup bond0 then re-set-up the slaves and IPs
Et voici le script du serveur. Il devrait ressembler beaucoup au script client en général, sauf que vous devez faire quelques iptables
transfert de paquets pour obtenir des paquets vers et depuis votre liaison montante Internet et l'interface bond0.
Heureusement, il y a non espaces réservés dans le script du serveur ...! Il suffit de copier, coller et exécuter. (Euh, à moins que vos deux interfaces auxquelles le client se connecte ne soient pas eth0
et eth1
.)
#!/bin/bash
#The next line should be executed before you start doing anything on the client; or you can set openvpn to automatically start on system boot if you prefer.
/etc/init.d/openvpn start
sleep 1
ifup bond0
sleep 1
#Not necessary if your ifenslave script is working properly, but I had to add them manually
echo '+tun0' > /sys/class/net/bond0/bonding/slaves
echo '+tun1' > /sys/class/net/bond0/bonding/slaves
#I honestly have no idea what this line does, but it's in the original blog post and it seems to be required :/
ip route add 10.0.0.0/8 via 172.26.0.2 dev bond0
iptables -A POSTROUTING -t nat -o eth0 -j MASQUERADE
iptables -A POSTROUTING -t nat -o eth1 -j MASQUERADE
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
#Optional, but again, the best active queue management around - see client script for details
tc qdisc add dev bond0 root fq_codel
#This gets inserted automatically at some point along the way; 169.254 is defined as unroutable so you definitely don't want that hanging around in there. Could be an artifact of using Amazon EC2, so this may error out for you with a "No such process" error if you don't get this route.
ip route del 169.254.0.0/16
... Et c'est à peu près tout.
Est-ce rapide ? Eh bien ... un peu. À ce stade, je ne suis pas époustouflé par les performances, mais cela me donne définitivement une vitesse supérieure à celle des liaisons les plus lentes, et j’ai utilisé l’outil pratique. iptraf
pour déterminer que les deux wlan0
et eth1
envoyez et recevez des paquets UDP lorsque je charge la passerelle par défaut (par exemple, en visitant des sites Web). Je cherche des possibilités d’accord entre MTU, MSS, tampon de réception, etc. pour améliorer les performances et optimiser le débit.