Debido a que en casa estamos cambiando de ISP, hemos tenido unas semanas de doble servicio, ¿qué experimentos podemos hacer que habitualmente no con una sola conexión?
Si no estuviera un poco aburrido del asunto de la ciberseguridad, me pondría a tirar nmaps y esas cosas... bueno, lo hice igual, pero la verdad es que más es interesante...
Multitier torrent
Normalmente cuando usas bittorrent, si estás bajando algo popular alcanzás una muy alta velocidad, limitada en última instancia por los componentes cercanos a vos, o sea, tu ISP.
El experimento que voy a realizar es comparar bajar el mismo contenido de distintas maneras teniendo múltiples (dos) ISPs.
Limitaciones
No me interesa explorar si hay algún cliente que sabe cómo lidiar con la situación, pues es algo que no puedo generalizar luego para otras aplicaciones.
No puedo usar dos placas de red, pues me consta que la máquina donde puedo poner varias placas por tener bus PCI tiene contención de ese mismo bus, en otra oportunidad me afectó.
No puedo usar un dongle USB-Ethernet pues baja considerablemente la velocidad.
Tampoco pienso poner una placa en mi máquina pues en los últimos cinco años he andado con mala suerte y se me ha roto una proporción desproporcionada de las máquinas que he abierto.
Tres escenarios
En realidad son dos pero necesito uno de referencia para poder comparar.
Referencia
Hay que medir primero la performance de cada ISP por separado. Para ello agrego un router que tenía tirado por ahí y le conecto otra máquina. En ambas bajo lo mismo.
Considerá que todos estos números son un tanto imprecisos, sobre todo los del ISP 1, pues la misma conexión está siendo usada a la vez por otras personas.
Medición ISP 1
Bajé el archivo completo:
- 3.86 GB
- 21 minutos 1260 segundos
- 3860398080 / 1260 = 3063808 B/s = 3.06 MB/s
- por momentos 3.65 MB/s
Medición ISP 2
Cuando llegó a 15 minutos me aburrí, tomé estos datos parciales
- 1.18 GB
- 15 minutos = 900 segundos
- 1180000000 / 900 = 1311112 B/s = 1.31 MB/s
- por momentos 1.54 MB/s
Vía ISP 2 |
Dos máquinas
Dos máquinas, cada una conectada a un ISP y aprovechar que mi cliente entiende buscar en la red local si hay alguien bajando lo mismo, de este modo quizás cada uno baje un mitad y la comparta con el otro.
Local Peer Discovery en ambas máquinas |
Para esto hay que:
- desactivar DHCP en el router del ISP2
- poner al router en una IP de la red del ISP1, por ejemplo 192.168.1.10
- poner a la máquina 2 con IP 192.168.1.11 y gateway 192.168.1.10
- tirar un cable del router al switch
- activar LPD en ambas máquinas
Pre prueba
Que una máquina vea a la otra en la red local y baje todo de ahí, ok, dejé que la segunda máquina terminara y anduvo.
Habiendo activado Local Peer Discovery |
Medición dos máquinas
- 3.86 GB
- 16 minutos, son 960 segundos
- 3860398080 / 960 = 4021248 B/s = 4MB/s
- Por momentos 7MB/s
Bajada combinando un ISP y la otra instancia |
Se ve la dirección local de la otra máquina |
Es conveniente ejecutar en ambas máquinas como root o sudo:
$> mii-tool enp3s0
enp3s0: negotiated 100baseTx-FD flow-control, link ok
enp3s0: negotiated 100baseTx-FD flow-control, link ok
y las velocidades deberían coincidir.
Una máquina, dos rutas
En lo anterior no he cumplido con ser neutral con respecto al cliente de bittorrent, no sé si otros programas soportan LPD. Tampoco puedo contar con tener dos computadoras y espacio libre en ambas, notá que aunque bajé una sola instancia de la imagen, la tengo duplicada.
Lo que hay que hacer ahora es:
- mantener el router del ISP2
- DHCP desactivado
- una IP estática conocida
- cable al switch de la red principal
- quitar la segunda máquina
- LPD ya no es necesario
- manipular sus rutas
Para manipular las rutas hace falta tener una vaga idea de cuál será la partición.
watch -n 10 netstat -tn >> ips.txt
toda la noche, me hice un mapa de las IPs típicas, el problema es que la salida me quedó con caracteres de escape, más o menos lo limpié con esto, seguro se puede hacer mejor:
strings ips.txt | grep "[01234567890.]*:443" -o \
| grep "\..*\..*\..*" | cut -d "." -f 1-2 \
| sort -n | uniq -c
Quitando los errores del comando anterior me deja:
6 1.13
5 2.16
2 2.18
2 2.43
7 3.77
2 52.1
7 6.58
62 8.43
1 8.67
3 13.33
1 15.96
6 16.58
1 16.73
1 16.74
30 2.217
8 23.12
1 23.32
1 23.55
104 23.77
52 3.107
194 31.13
3 3.223
3 3.232
4 34.98
2 4.233
12 4.244
1 45.54
10 5.201
131 52.43
54 68.67
1 86.18
1 88.99
70 92.16
31 104.87
1 115.96
148 13.107
7 13.227
1 144.76
1 185.63
7 186.18
113 192.16
1 192.73
15 200.42
260 216.58
5 23.197
10 23.222
2 34.194
199 35.201
1 35.241
2 52.195
1 54.187
1 54.219
170 64.233
297 72.217
1 74.119
2 74.125
3 95.216
99 104.244
4 104.254
1 108.174
1 151.101
16 152.195
1 152.199
953 172.217
22 192.168
y agrupando a ojo:
5 2.16
2 2.18
2 2.43
7 3.77
2 52.1
7 6.58
62 8.43
1 8.67
3 13.33
1 15.96
6 16.58
1 16.73
1 16.74
30 2.217
8 23.12
1 23.32
1 23.55
104 23.77
52 3.107
194 31.13
3 3.223
3 3.232
4 34.98
2 4.233
12 4.244
1 45.54
10 5.201
131 52.43
54 68.67
1 86.18
1 88.99
70 92.16
31 104.87
1 115.96
148 13.107
7 13.227
1 144.76
1 185.63
7 186.18
113 192.16
1 192.73
15 200.42
260 216.58
5 23.197
10 23.222
2 34.194
199 35.201
1 35.241
2 52.195
1 54.187
1 54.219
170 64.233
297 72.217
1 74.119
2 74.125
3 95.216
99 104.244
4 104.254
1 108.174
1 151.101
16 152.195
1 152.199
953 172.217
22 192.168
y agrupando a ojo:
- redes entre 1.0.0.0 y 63.0.0.0 = 700
- redes entre 64.0.0.0 y 127.0.0.0 = 1500
- redes entre 128.0.0.0 y 255.0.0.0 = 1000
Ojo otra vez, esas IPs son las conexiones que hubieron durante un tiempo, no es un buen análisis pues no tengo idea del tráfico que hubo que es lo que realmente me interesa para particionar.
Veamos primero que hay:
$> route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 100 enp3s0
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 enp3s0
192.168.1.0 0.0.0.0 255.255.255.0 U 100 0 0 enp3s0
Kernel IP routing table
Destination Gateway Genmask Flags Metric Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 100 enp3s0
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 enp3s0
192.168.1.0 0.0.0.0 255.255.255.0 U 100 0 0 enp3s0
Lo que tengo que agregar es una ruta tal que el Gateway sea el router que conduce al ISP 2, esto es, 192.168.1.10. Luego usando dos servicios de identificación de cuál es mi IP, ver que uno me dice una y otro la otra.
Tengo dos, con ping -c 1 obtengo sus IP
https://whatismyipaddress.com 104.16.155.36
https://www.whatismyip.com 104.27.199.91
ufa, están muy juntas.
https://www.myip.com 172.67.208.45
Mejor, de paso ya hago el particionado en 128.0.0.0, todos los route add son como root.
Lo que nos da:
$> route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 100 0 0 enp3s0
128.0.0.0 192.168.1.10 128.0.0.0 UG 100 0 0 enp3s0
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 enp3s0
192.168.1.0 0.0.0.0 255.255.255.0 U 100 0 0 enp3s0
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 100 0 0 enp3s0
128.0.0.0 192.168.1.10 128.0.0.0 UG 100 0 0 enp3s0
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 enp3s0
192.168.1.0 0.0.0.0 255.255.255.0 U 100 0 0 enp3s0
Observá las distintas IPs según a quien le preguntes |
Listo para torrentear.
En uno de los momentos de máxima velocidad |
- 3.86 GB
- 17 minutos 1020 segundos
- 3860398080 / 1260 = 3063808 B/s = 3.78 MB/s
- por momentos 4.77 MB/s
Resultados y reflexiones
Aun con un particionado muy bestia como el que he realizado, se pueden combinar exitosamente las velocidades de dos o más ISP.
Modo | tiempo [s] | velocidad [MB/s] | pico [MB/s] |
ISP 1 | 1260 | 3.06 | 3.65 |
ISP 2 | 1.31 | 1.54 | |
Dos máquinas | 960 | 4 | 7 |
Dos rutas | 1020 | 3.78 | 4.77 |
El pico no es muy representativo, en "Dos Máquinas" indica lo que ocurrió en la LAN. Lo interesante es que la red local de 100 Mb está prácticamente saturada, si agregara un tercer proveedor como el primero no lo podría aprovechar completamente, tendría que usar una red interna de 1Gb.
Siguientes pasos
Me interesa mucho este tema, pero dentro de dos días me quedo sin el segundo ISP y la verdad es que no me paso el día bajando cosas y tengo otras muchas tan o más interesantes que hacer, lo que sigue te puede servir de inspiración para que lo hagas vos. ¿No tenés dos ISP? No hay problema, le pedís a un vecino que tenga WiFi con un proveedor distinto al tuyo mejor que te preste sus credenciales y ya tenés dos ISPs, o tres o más.
Distribución mediante DHCP
Todo lo que hice antes fué en una sola máquina, si querés que todas tus máquinas tomen esa configuración, parece que con DHCP se puede.
Balanceo dinámico con ruteo
Si tenés varios canales como es este caso y además tenés el control en ambos extremos, el balanceo debe ser sencillo, en particular en una red local lo he hecho usando trunking/bonding.
Para el caso actual, donde están de un sólo lado del caño, no es tan sencillo, habría que estar midiendo cual es el mejor camino, una combinación de ancho de banda, latencia, saltos hasta el destino. Debe existir una manera común y normal pero para mejor aprender e investigar voy a seguir sin buscarla y pensando.
Para ver el tráfico discriminado se me ocurre agregar una interfaz virtual, de este modo se puede ver la saturación y si a la vez mirás netstat, podrías ir reparticionando. Cuando le pescaste la mano, reemplazás con un script. Pero no debe ser ten fácil, ¿qué pasa con una conexión que tenés abierta si cambia el enrutamiento? ¿El kernel se dá cuenta y no te la corta? Ahí recordé que man route ofrece:
-C operate on the kernel's routing cache.
Lo que me llevó a que manipulating the routing tables may not have an
immediate effect on the kernel's choice of path for a given packet puede tener un efecto mitigante.
Parece que el kernel tiene un cache y que a menos que uno le pida explícitamente, add no lo toca. Esto no sólo salvaría a una conexión existente si no que muchas otras conexiones nuevas no tomarían la nueva ruta, debe haber un TTL por ahí.
Es todo un tema, listo, ya me cansé de pensarlo.
Si ponés en google algo así como
"dynamically changing routes to balance traffic between two providers"
tenés para divertirte.
No hay comentarios:
Publicar un comentario