A todos nos pasa en algún momento que a un vecino le agarra un ataque de locura, sale corriendo en calzones a la calle gritando su contraseña wifi.. no no?

Bueno, supongamos que por un bug el router guarda su password en el campo del SSID sin querer y nosotros podemos conectarnos libremente... tampoco no ?

Cualquiera que tenga mas de 1 salida a internet en su casa, seguro alguna vez se preguntó cómo podría hacer para unificar ambas conexiones o sumar el ancho de banda, para poder navegar a mas alta velocidad, o descargar comprar películas más rápido.

Con Linux, haciendo uso de iptables e iproute2, es bastante sencillo. Lo que vamos a hacer, en resumidas cuestiones es:

  • Armar 2 tablas de routing
  • Configurar iptables para que marque los paquetes de salida (2 marcas distintas) con un 50% de probabilidad para c/u de las marcas
  • Configurar reglas de routing para que salga por uno u otro gateway según la marca que tenga
  • Descargar comprar mucho contenido multimedia

Para dar un poco más de luz sobre el tema, cabe aclarar que los anchos de banda no se suman como haciendo 2+2. La verdadera diferencia de velocidad se va a ver en aplicaciones que utilicen múltiples conexiones simultáneas hacia afuera, ya que por la forma de funcionamiento, las conexiones son routeadas con un 50% de probabilidad hacia cada salida.

Por ejemplo, si descargamos un torrent, vamos a ver una gran diferencia (dependiendo de la velocidad de las conexiones a internet), pero si abrimos una URL que es un JPG de 50mb en el browser, no vamos a notar diferencia, ya que se está usando 1 sola conexión y fué routeada por 1 de las salidas a internet.

Así que en resúmen, la gran diferencia se nota al hacer uso de sistemas p2p, navegar sitios web, usar aceleradores de descarga o cualquier otra aplicación con múltiples conexiones simultáneas.

Empecemos

Routing tables

Primero tenemos que definir una tabla de routeo por cada salida a internet que tengamos. Para hacer eso, editamos el archivo /etc/iproute2/rt_tables :

255    local  
254    main  
253    default  
20    inet2  
10    inet1  
0    unspec  

Tendrán que añadir 2 nuevas lineas, con un identificador unico. Yo usé 10 para inet1 y 20 para inet2.

Rutas

Una vez que tenemos las tablas definidas, tenemos que armar las rutas para cada tabla. Supongamos que tenemos 2 interfaces de red, con la siguiente configuración:

eth0 (usaremos la tabla inet1)
ip: 192.168.0.10
gateway: 192.168.0.1

eth1 (usaremos la tabla inet2)
ip: 192.168.2.5
gateway: 192.168.2.1

ip route add table 10 default via 192.168.0.1  
ip route add table 20 default via 192.168.2.1  

Iptables

Mediante algunas reglas, como habíamos dicho, vamos a usar 2 marcas en los paquetes, dandole un 50% de probabilidad a cada uno, lo que haría un balance bastante parejo.

Si tenemos las conexiones con distinta velocidad, podríamos darle un poco más de probabilidad a una marca que a otra, pero esos ajustes finos ya quedan en manos de cada uno.

iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark  
iptables -t mangle -A OUTPUT -m mark ! --mark 0 -j RETURN  
iptables -t mangle -A OUTPUT -m state --state ESTABLISHED,RELATED -j RETURN  
iptables -t mangle -A OUTPUT -j MARK --set-mark 10  
iptables -t mangle -A OUTPUT -m statistic --mode random --probability 0.5 -j MARK --set-mark 20  
iptables -t mangle -A OUTPUT -j CONNMARK --save-mark  

Enmascarar salida

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE  
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE  

Reglas de routeo

Ahora, vamos a indicarle al sistema el camino de red que tiene que tomar según la marca definida.

*Nota: Yo use como marcas 10 y 20, pero no tienen necesariamente que coincidir con los números de la routing table. Yo lo hice así para que se entienda un poco mejor.

ip rule add fwmark 10 table 10 prio 30000  
ip rule add fwmark 20 table 20 prio 30001  

Con eso le decimos, que los paquetes con la marca 10 agarren las rutas de la tabla 10 (inet1), y los paquetes con la marca 20 agarren las rutas de la tabla 20 (inet2).

Parámetros del kernel

Para terminar el tema, hace falta configurar unos parámetros del kernel que filtran paquetes entrantes, y puede interferir con la configuración realizada:

sysctl -w net.ipv4.conf.eth0.rp_filter=0  
sysctl -w net.ipv4.conf.eth1.rp_filter=0  
sysctl -w net.ipv4.conf.all.rp_filter=0  
sysctl -w net.ipv4.conf.default.rp_filter=0  

No voy a entrar en detalle sobre qué hacen esos parámetros, pero si les interesa pueden leer un poco de documentación.

Usamos eth0 y eth1, pero deberían reemplazar esos nombres por los nombres de sus interfaces.

Eso es todo! próximamente voy a publicar una variante para poder funcionar como gateway y balancear paquetes forwardeados.

:wq!