Conexiones OpenVPN redundantes con enrutamiento avanzado de Linux a través de una red poco confiable

9

Actualmente estoy viviendo en un país que bloquea muchos sitios web y tiene conexiones de red poco confiables con el mundo exterior. Tengo dos puntos finales OpenVPN (por ejemplo: vpn1 y vpn2) en los servidores de Linux que uso para sortear el firewall. Tengo acceso completo a estos servidores. Esto funciona bastante bien, excepto por la gran pérdida de paquetes en mis conexiones VPN. Esta pérdida de paquetes varía entre 1% y 30% dependiendo del tiempo y parece tener una baja correlación, la mayoría de las veces parece aleatoria.

Estoy pensando en configurar un enrutador doméstico (también en Linux) que mantenga conexiones OpenVPN a ambos puntos finales y envíe todos los paquetes dos veces, a ambos puntos finales. vpn2 enviaría todos los paquetes desde casa a vpn1. El tráfico de retorno se enviaría directamente desde vpn1 a casa y también a través de vpn2.

       +------------+
       |    home    |
       +------------+
        |          |
        | OpenVPN  |
        |  links   |
        |          |
     ~~~~~~~~~~~~~~~~~~ unreliable connection
        |          |
+----------+   +----------+
|   vpn1   |---|   vpn2   |
+----------+   +----------+
        |
       +------------+
       | HTTP proxy |
       +------------+
             |
         (internet)

Para mayor claridad: todos los paquetes entre el hogar y el proxy HTTP se duplicarán y se enviarán a través de diferentes rutas, para aumentar las posibilidades de que llegue uno de ellos. Si ambos llegan, el primer segundo puede descartarse en silencio.

El uso del ancho de banda no es un problema, tanto en el lado local como en el extremo. vpn1 y vpn2 están cerca uno del otro (ping de 3 ms) y tienen una conexión confiable.

¿Algún indicador sobre cómo se podría lograr esto utilizando las políticas de enrutamiento avanzadas disponibles en Linux?

Konrad
fuente

Respuestas:

8

Use la infraestructura de enlace en el lado 'home' y 'vpn1', y específicamente con la configuración mode = 3 que transmite el tráfico en todas las interfaces que pertenecen a un enlace.

Para obtener más información sobre cómo configurar la vinculación, consulte el excelente manual en http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.37.y.git;a=blob;f = Documentación / networking / bonding.txt; h = 5dc638791d975116bf1a1e590fdfc44a6ae5c33c; hb = HEAD

jap
fuente
Probé esta configuración y funciona de maravilla. ¡La pérdida de paquetes se reduce de alrededor del 5% al ​​0.0-0.1% con una conexión redundante a un solo servidor!
konrad
7

Utilicé la respuesta proporcionada por @ user48116 y funciona de maravilla. ¡La configuración es realmente bastante fácil!

NOTA : Implementé esto con dos conexiones a un solo servidor, ya que esto ya resolvió el problema para mí. Si desea probar una configuración con dos servidores, la forma más fácil es usar el reenvío de puertos para reenviar el puerto UDP del segundo servidor al primero y usar la misma receta que se describe aquí. Sin embargo, no lo he probado yo mismo.

Primero, asegúrese de tener un kernel 2.6 con soporte de enlace (predeterminado en todas las distribuciones modernas) y que tenga instalado ifenslave.

A continuación, coloque esto en su /etc/rc.local o en cualquier otro lugar que prefiera, pero asegúrese de que se ejecute antes de que se inicie openvpn (porque intentará unirse a bond0):

Cliente:

modprobe bonding mode=broadcast
ifconfig bond0 10.10.0.2 netmask 255.255.255.0 up

Puede agregar algunas rutas si es necesario aquí, asegúrese de hacer todas las rutas correctas desde el otro lado también.

route add -net 10.7.0.0/24 gw 10.10.0.1

Servidor:

modprobe bonding mode=broadcast
ifconfig bond0 10.10.0.1 netmask 255.255.255.0 up

Cree un script /etc/openvpn/tap-up.sh (y no olvide marcarlo como ejecutable con chmod a + x tap-up.sh):

#!/bin/sh
# called as: cmd tap_dev tap_mtu link_mtu ifconfig_local_ip ifconfig_netmask [ init | restart ]
ifenslave bond0 "$1"

A continuación, agregue un bridge0a.conf y bridge0b.conf a / etc / openvpn / junto con una clave compartida. Los archivos son los mismos para ayb, excepto para un puerto diferente (por ejemplo, use 3002 para b). Reemplace 11.22.33.44 por la IP pública de su servidor.

Cliente:

remote 11.22.33.44
dev tap
port 3001
rport 3001
secret bridge.key
comp-lzo
verb 4
nobind
persist-tun
persist-key
script-security 2
up /etc/openvpn/tap-up.sh

Servidor:

local 11.22.33.44
dev tap
port 3001
lport 3001
secret bridge.key
comp-lzo
verb 4
script-security 2
up /etc/openvpn/tap-up.sh

No olvide editar / etc / defaults / openvpn para asegurarse de que se inicien sus nuevas configuraciones de VPN. Reinicie sus máquinas, o cargue rc.local y reinicie openvpn manualmente.

Ahora estás listo para probar tu configuración:

# ping 10.10.0.1
PING 10.10.0.1 (10.10.0.1) 56(84) bytes of data.
64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=50.4 ms
64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=51.1 ms (DUP!)
64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=51.1 ms (DUP!)
64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=51.1 ms (DUP!)
64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=52.0 ms
64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=52.2 ms (DUP!)
64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=53.0 ms (DUP!)
64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=53.1 ms (DUP!)
--- 10.10.0.1 ping statistics ---
2 packets transmitted, 2 received, +6 duplicates, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 50.428/51.786/53.160/0.955 ms

Si todo va bien y la línea es buena, verá cuatro respuestas para cada paquete ICMP: sus paquetes se duplican en el lado local, y las respuestas a estos dos paquetes se duplican nuevamente en el lado remoto. Esto no será un problema para las conexiones TCP, porque TCP simplemente ignorará todos los duplicados.

Este es un problema para los paquetes UDP, ya que depende del software manejar duplicados. Por ejemplo, una consulta DNS generará cuatro respuestas en lugar de las dos esperadas (y usará cuatro veces el ancho de banda normal para la respuesta en lugar de dos veces):

# tcpdump -i bond0 -n port 53
listening on bond0, link-type EN10MB (Ethernet), capture size 65535 bytes
13:30:39.870740 IP 10.10.0.2.59330 > 10.7.0.1.53: 59577+ A? serverfault.com. (33)
13:30:40.174281 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49)
13:30:40.174471 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49)
13:30:40.186664 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49)
13:30:40.187030 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49)

¡Buena suerte!

Konrad
fuente