networking – ¿Existe alguna forma de optimizar el tráfico de paquetes cifrados a través de múltiples conexiones a Internet?

Pregunta:

Quiero lograr esto:

  • Combine múltiples conexiones a Internet.
  • Cifre la conexión desde la computadora local al servidor proxy / VPN remoto.
  • Lo ideal es cambiar entre los modos "Confiable" y "Velocidad" (que se describen a continuación). Si esto no es posible, entonces preferiría al menos poder usar el modo Channel Bonding (Speed).
  • Tener el software del servidor alojado en mi propia infraestructura (como un servidor dedicado o VPS).
  • Idealmente, la solución debería poder ejecutarse en un cliente Windows que se conecta a un servidor Linux. (por ejemplo, Windows 10 en el cliente, Ubuntu 14.04 Server en el servidor). Si se requiere un cliente Linux, indíquelo en su respuesta; sigue siendo una respuesta aceptable si requiere un cliente Linux, siempre puedo ejecutarlo en una máquina virtual si es necesario.

¿Cómo puedo hacer esto ?


Mas detalle

Modos confiables frente a rápidos

El modo confiable es como RAID-1, donde los mismos paquetes se envían en dos o más enlaces ascendentes, y se toma el primer paquete que llega al servidor, mientras que la otra copia se desecha. En modo confiable, su rendimiento total es teóricamente el más rápido de sus dos enlaces ascendentes, pero en la práctica es un poco menor si los paquetes del enlace ascendente más lento a veces llegan primero al punto final.

El modo de velocidad es como RAID-0, donde se envían diferentes paquetes de datos a través de ambos enlaces para que su rendimiento total, por ejemplo, en una descarga, sea la suma del rendimiento de ambos enlaces ascendentes.

Speedify usa este mecanismo, más información aquí . Simplemente podría usar eso, excepto que el propio servicio de Speedify no encripta los datos, y uno de mis dos enlaces ascendentes es un punto de acceso WiFi no seguro; Necesito un cifrado fuerte para proteger los protocolos de aplicación que no están cifrados en sí mismos (como el HTTP normal al que se accede a superuser.com).

Mi situación

Tengo dos conexiones a la Internet pública:

  • Una conexión LTE de ~ 12 Mbps como un adaptador Ethernet sobre USB (en realidad es un iPhone, pero se expone al sistema operativo como Ethernet normal)
  • Una conexión LTE de ~ 5 Mbps desde un punto de acceso WiFi, entregada a un dongle USB 802.11ac

Quiero combinarlos de la siguiente manera:

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

El final de la Internet Activity es donde se pone peligroso. Quiero tener dos conexiones separadas establecidas entre mi computadora local y el Server , pero una conexión unificada establecida entre el Server y la Internet pública en general.

Entonces, por ejemplo, digamos que envío una solicitud HTTP que toma, digamos, 10 paquetes IP. Quizás 6 de esos paquetes se enviarían a través de la Conexión A y 4 a través de la Conexión B. Ese desglose se basaría en el nivel de saturación de cada enlace ascendente. Esto es lo que hace Speedify, pero Speedify no cifra nada.

Esos paquetes se enviarán en el orden correcto desde el Server a cualquier punto final en la Internet pública al que esté tratando de llegar.

Luego, cuando la Respuesta HTTP regrese de la Web, volvería como 10 paquetes que luego se pasan a través del Server y se distribuyen de regreso a la Connection A y la Connection B de una manera que intenta evitar la congestión de la red (por lo tanto, si uno de los enlaces ascendentes tiene mucha pérdida o saturación de paquetes, se concentraría en usar el otro enlace ascendente, pero si los paquetes llegan a ambos enlaces, los distribuiría a través de ambos enlaces dependiendo de la velocidad del enlace).

Esa es la esencia de lo que ocurriría detrás de escena. Consideré la posibilidad de usar algo como OpenVPN. Sin embargo, no estoy familiarizado con si podría configurarse para hacer esto o cómo.

Mi pregunta

No busco una lista de sugerencias de software que puedan resultar útiles. Más bien, mi pregunta es ¿cuáles son los detalles de cómo lograr esto?

Respuesta:

Un tiempo después de publicar esta pregunta, cambié algunos términos en mis búsquedas de Google y encontré la siguiente joya de una publicación de blog: http://simonmott.co.uk/vpn-bonding

El artículo es extenso y proporciona toda la información necesaria para que esto funcione. Sin embargo, hay una falla significativa en el enfoque adoptado por el autor. Al hacer un túnel a través de SSH, está haciendo que el túnel de transporte sea TCP . Ack. Eso significa que si canaliza TCP a través del túnel, tiene TCP encima de TCP. Con cualquier latencia significativa o pérdida de paquetes, las pilas de TCP se confundirán y comenzarán a romperse cuando ambas pilas de TCP intenten lidiar con algoritmos de control de congestión, retransmisiones, etc. Esto limita severamente su rendimiento a menos que solo use algo como UDP dentro del túnel (lo que significa que no puede acceder a la Web).

El artículo menciona que funcionará de manera equivalente con algo que no sea ssh como túnel, y tiene razón . Decidí usar la función punto a punto de OpenVPN para esto. No es extremadamente seguro ya que usa una clave estática, pero la seguridad fue lo suficientemente buena para mis propósitos (prácticamente solo las Amenazas Persistentes Avanzadas podrán romper la criptografía).

OpenVPN puede transportar a través de TCP o … ¡ UDP ! Queremos hacer que la capa de transporte de nuestro túnel sea UDP, porque si los paquetes se pierden, la capa TCP "interna" se ocupará del control de la congestión. Y si ejecuta UDP dentro de UDP, el código de la aplicación es responsable de lidiar con la pérdida o latencia de paquetes, y tenderá a manejarlo bien.

Me encontré con un problema importante en forma de regresión del kernel que se produjo en algún momento durante un lanzamiento puntual de la serie 3.13, y no se ha abordado ni siquiera en el git master de torvalds en este momento. Esto no se menciona en el artículo porque la regresión no existía en el momento en que se escribió la publicación. Tanto en su cliente como en su servidor, necesitará recompilar su kernel con este parche (lo suficientemente simple como para aplicarlo manualmente si el patch niega a funcionar), o usar una versión del kernel de 3.13.0 o anterior.

Para mis propósitos, usé Debian Wheezy (actualmente la rama antigua oldstable de Debian) con el kernel 3.2 para el servidor, porque no quería recompilar mi kernel en un VPS t2.nano de Amazon EC2. En el lado del cliente (un escritorio Linux Mint), fui con la recompilación del kernel. Entonces, ambos métodos funcionan.

Aquí están las instrucciones para configurar esto una vez que recompile su kernel:

openvpn cuatro procesos openvpn : dos en el cliente y dos en el servidor. Use openvpn versión 2.1 o posterior, de lo contrario, esto no funcionará. Coloque los archivos en el directorio / etc / openvpn (a menos que tenga un sysconfdir personalizado y un openvpn compilado de manera personalizada).

En mi caso, tengo dos NIC separadas, eth0 y eth1 en el servidor, que proporcionan dos IP públicas separadas, abreviadas debajo de SERVER_IP1 y SERVER_IP2 . En el cliente, tengo eth1 y wlan0 conectados a mis enlaces ascendentes de Internet, y sus puertas de enlace (que se encuentran usando ifconfig y route -n ) se abrevian como GW1 y GW2 .

Para crear static.key , lea la página de manual de OpenVPN.

Servidor tun0.conf:

dev tun0
local SERVER_IP1
proto udp
topology p2p
push "topology p2p"
secret static.key
keepalive 30 90

Servidor tun1.conf:

dev tun1
local SERVER_IP2
proto udp
topology p2p
push "topology p2p"
secret static.key
keepalive 30 90

Cliente Tun0.conf:

dev tun0
nobind
remote SERVER_IP1
proto udp
topology p2p
secret static.key

Cliente Tun1.conf:

dev tun1
nobind
remote SERVER_IP2
proto udp
topology p2p
secret static.key

Ahora desea iniciar las instancias de OpenVPN en el servidor primero y luego en el cliente.

Una vez que tenga tun0 y tun1 conectados en modo POINTOPOINT (debería decir que en la descripción de la interfaz cuando se ejecuta ifconfig ), bond0 listo para configurar el enlace de enlace, bond0 .

Asumiré que está utilizando Debian, Ubuntu o una bifurcación de los mismos para los archivos de configuración. Puede hacer una configuración equivalente en sistemas basados ​​en CentOS / RHEL en /etc/sysconfig/network-scripts/ifcfg-bond0 , si /etc/sysconfig/network-scripts/ifcfg-bond0 no recuerdo. Tendrá que ajustar la sintaxis de configuración para ese tipo de sistema operativo. Y las cosas pueden cambiar significativamente en un futuro cercano con la introducción de systemd y su demonio de red.

De todos modos, agregue esto a /etc/network/interfaces en el servidor:

iface bond0 inet static
    address 172.26.0.1
    netmask 255.255.255.252
    bond-slaves tun0 tun1
    bond_mode balance-rr

Y sobre el cliente:

iface bond0 inet static
    address 172.26.0.2
    netmask 255.255.255.252
    bond-slaves tun0 tun1
    bond_mode balance-rr

Asegúrese de que ifenslave sea ​​un comando válido en la línea de comandos antes de continuar. Si no es así, instálelo desde su administrador de paquetes, con algo como sudo apt-get install ifenslave .

También asegúrese de descomentar la línea que dice #net.ipv4.ip_forward=1 en /etc/sysctl.conf , y puede que tenga que echo 1 > /proc/sys/net/ipv4/ip_forward si no quiere reinicie después de realizar el cambio a /etc/sysctl.conf .

Aquí está mi guión de inicio para el cliente; tendrá que reemplazar varios valores de marcador de posición (SERVER_IP1, SERVER_IP2, GW1, GW2, eth1 y wlan0 , etc.) para que funcione para usted.

No reemplace 172.26.0.1 / 172.26.0.2 con cualquier cosa; son IP privadas elegidas arbitrariamente que corresponden al enlace bond0 del servidor y al enlace bond0 del cliente, respectivamente.

#!/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

Y aquí está el script del servidor. Debería verse bastante similar a la secuencia de comandos del cliente en general, excepto que debe realizar algunos reenvíos de paquetes de iptables para obtener paquetes desde y hacia su enlace ascendente de Internet y la interfaz bond0.

¡Felizmente, no hay marcadores de posición en el script del servidor …! Simplemente copie, pegue y ejecute. (Err, a menos que sus dos interfaces a las que se conecta el cliente no sean eth0 y 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

… Y eso es todo.

Es rapido Así un poco. En este punto, no estoy impresionado por el rendimiento, pero definitivamente me está dando mejores velocidades que el más lento de los dos enlaces, y utilicé la práctica herramienta iptraf para determinar que tanto wlan0 como eth1 están enviando y recibiendo paquetes UDP cuando poner carga en la puerta de enlace predeterminada (por ejemplo, visitando sitios web). Estoy buscando posibles ajustes en la forma de MTU, MSS, búfer de recuperación, etc. para mejorar el rendimiento y optimizar el rendimiento.

Leave a Comment

Your email address will not be published.

Scroll to Top

istanbul avukat

-

web tasarım