Existe-t-il un moyen d’optimiser le trafic de paquets cryptés sur plusieurs connexions Internet?

7

Je veux accomplir ceci:

  • Combinez plusieurs connexions Internet.
  • Cryptez la connexion de l'ordinateur local au serveur proxy / VPN distant.
  • Idéalement, basculez entre les modes "Fiable" et "Vitesse" (décrits ci-dessous). Si cela n’est pas possible, je préférerais au moins pouvoir utiliser le mode Channel Bonding (Speed).
  • Faire héberger le logiciel serveur sur ma propre infrastructure (comme un serveur dédié ou VPS).
  • Idéalement, la solution devrait pouvoir fonctionner sur un client Windows se connectant à un serveur Linux. (par exemple, Windows 10 sur le client, Ubuntu 14.04 Server sur le serveur.) Si un client Linux est Champs obligatoires , veuillez l'indiquer dans votre réponse. c'est toujours une réponse acceptable si cela nécessite un client Linux, je peux toujours l'exécuter dans une machine virtuelle si nécessaire.

Comment puis-je faire ceci ?


Plus de détails

Modes fiables et rapides

Mode fiable est semblable à RAID-1, où les mêmes paquets sont envoyés sur deux liaisons montantes ou plus, et le premier paquet qui atteint le serveur est pris, tandis que l'autre copie est jetée. En mode fiable, votre débit total est théoriquement le plus rapide de vos deux liaisons montantes, mais en pratique est un peu moins si les paquets de la liaison montante plus lente atteignent parfois le point final en premier.

Mode vitesse est semblable à RAID-0, où différents paquets de données sont envoyés sur les deux liaisons, de sorte que votre débit total, par ex. sur un téléchargement, est l'ajout du débit des deux liaisons montantes.

Speedify utilise ce mécanisme, plus d'infos ici . Je pourrais simplement l'utiliser, sauf que le service de Speedify ne crypte pas les données et que l'une de mes deux liaisons montantes est un point d'accès WiFi non sécurisé; J'ai besoin d'un cryptage fort pour protéger les protocoles d'application qui ne sont pas eux-mêmes cryptés (comme le protocole HTTP classique sur lequel superuser.com est utilisé).

Ma situation

J'ai deux connexions à l'Internet public:

  • Une connexion LTE ~ 12 Mbps en tant qu'adaptateur Ethernet sur USB (il s'agit en fait d'un iPhone, mais il est exposé au système d'exploitation en tant qu'Ethernet classique)
  • Une connexion LTE de ~ 5 Mbps à partir d’un point d’accès WiFi, livrée à une clé USB 802.11ac

je veux combiner comme suit:

Connection A --> Internet --> Server --> Internet Activity
Connection B --> Internet --> Server --> Internet Activity

le Internet Activity la fin est où il devient risqué. Je veux en avoir deux séparé connexions établies entre mon ordinateur local et Server, mais un unifié connexion établie entre Server et l'Internet public plus large.

Ainsi, par exemple, supposons que je soumette une demande HTTP qui prend, disons, 10 paquets IP. Peut-être que 6 de ces paquets seraient envoyés sur la connexion A et 4 sur la connexion B. Cette répartition serait basée sur le niveau de saturation de chaque liaison montante. C'est ce que Speedify fait, mais Speedify ne chiffre rien.

Ces paquets seraient envoyés dans le bon ordre à partir de Server à tout point final sur l'Internet public que j'essaie d'atteindre.

Ensuite, lorsque la réponse HTTP revient du Web, elle retourne sous forme de 10 paquets qui sont ensuite transmis Server et redistribué à Connection A et Connection B de manière à éviter l’encombrement du réseau (donc, si l’une des liaisons montantes subit beaucoup de pertes de paquets ou de saturation, elle se concentrera sur l’utilisation de l’autre liaison montante, mais si des paquets parviennent à les traverser, elle les distribuera sur les deux liens en fonction de la vitesse de liaison).

Voilà l'essentiel de ce qui se passerait dans les coulisses. J'ai envisagé d'utiliser éventuellement quelque chose comme OpenVPN. Cependant, je ne sais pas si ni comment cela pourrait être configuré pour le faire.

Ma question

Je ne cherche pas une liste de suggestions de logiciels qui pourraient être utiles. Ma question est plutôt de savoir quels sont les détails de la manière de procéder.

allquixotic
la source
3
Comment puis-je écrire cela pour qu'il soit ne pas une demande de recommandation de logiciel? Mon message ne correspond-il pas exactement au format expliqué par @JourneymanGeek? ici ? Je pense que les gens sont un peu trop satisfaits de la gâchette avec le tout "OMG, c'est un logiciel-rec, tuez-le !!" mentalité. J'ai même spéculé sur le fait que je pense qu'OpenVPN pourrait être une solution, mais je n'ai trouvé aucune configuration permettant explicitement de rendre possible ce que j'essaie de faire, mais je souhaite également éviter X / Y en ne me limitant pas à OpenVPN si une autre solution serait meilleure.
allquixotic
Je pense qu’un bon point de départ serait de comprendre le fonctionnement de TCP et son implémentation à l’aide du protocole UDP ainsi que le fonctionnement des ordonnanceurs / répartiteurs. Vous aurez un répartiteur qui envoie des paquets en fonction d'une sorte de paramètre. Étant donné que vous envoyez initialement 2 liaisons, le serveur devra les réassembler dans le bon ordre (probablement une sorte de file d'attente / tampon qui modifie également les adresses ou peut-être supprime les données et crée de nouveaux paquets) - voir TCP numéros de séquence
nijave
Après un examen plus approfondi, vous devriez peut-être examiner le fonctionnement des protocoles de routage (BGP / OSPF / RIP / EIGRP). Fondamentalement, vous voulez juste un routeur à chaque extrémité et un seul point d’entrée dans chaque routeur. Vous devriez pouvoir consulter le code source OpenVPN pour voir comment fonctionne le routage. Il suffirait de le modifier pour prendre en charge plusieurs terminaux.
nijave
Pour Windows, vous avez Association de cartes d'interface réseau (NIC) , qui est une solution logicielle, mais qui semble s’appliquer uniquement à Windows Server à partir de 2012 R2.
harrymc

Réponses:

4

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-bond0si 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.confet 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.

allquixotic
la source