El año pasado vi un vídeo de una Google Tech Talk de Costin Raiciu (University Politehnica of Bucharest) y Christoph Paasch (Universite Catholique de Louvain) sobre Multipath TCP y me interesó mucho. Por cuestiones de tiempo y proyectos no me animé a probarlo, pero ha llegado el momento!
En este post veremos dos ejemplos prácticos que he realizado en laboratorio.
Multipath TCP o mptcp, es una extensión del protocolo tcp que permite multiplexar varias conexiones tcp sobre diferentes rutas.
Para concretar un poco y no extenderme demasiado, sobre un segmento tcp estándar observaríamos una nueva opción en la cabecera tcp.
Esta opción es la tipo 30 y está reservada por la IANA. Lo veremos en una captura en este post.
- Veamos un ejemplo teórico:
Un smartphone conectado por 3G/LTE/4G y wireless simultáneamente, inicia una descarga de un fichero grande de un servidor web remoto.
El smartphone pierde cobertura wireless mientras está descargando el fichero, pero mantiene cobertura 3G/4G/LTE.
Gracias a multipath tcp ( mptcp ) la descarga no se cortaría. Nota: iOS 7 soporta mptcp
- Condiciones:
Para que multipath tcp funcione, tanto cliente como servidor deben “hablar” multipath tcp.
Si en el tránsito de los paquetes, algún elemento filtra estos campos de la cabecera, el flujo tcp hará “fallback” a tcp estándar.
Por lo tanto, esta compatibilidad “hacia atrás” es muy buena para garantizar la comunicación.
- Ventajas:
Funciona en capa 4 OSI.
Las aplicaciones no necesitan cambios.
Es compatible con TCP estándar.
Provee redundancia en el cliente.
Mayor throughput.
Tolerancia a fallos.
- Desventajas:
Algunos firewalls filtran estos campos tcp nuevos, pero mptcp hará fallback a tcp estándar (esto lo analizaremos con un firewall Cisco ASA en este post).
Actualmente se le puede considerar muy nuevo ( rfc del 2013 ) y por tanto requiere modificaciones en el kernel de los OS’s de servidores en producción que no lo soporten. Sin embargo, se puede solventar usando un balanceador compatible mptcp ( He leído que Citrix NetScaler y F5 lo son ).
Nuevas cabeceras: potencialmente nuevos vectores de ataque. No he encontrado exploits 😉
- Vamos a los ejemplos prácticos!
El primer ejemplo lo he realizado sobre una LAN.
Además veremos:
El proceso de configuración de MPTCP sobre Linux
Gráficas de cacti durante el fallo de un enlace.
Veremos Netstats, iperfs e iptrafs
El segundo ejemplo es saliendo a internet, atravesando nat’s y un firewall Cisco ASA.
Además realizaremos una captura tcpdump y visualizaremos una de las opciones MPTCP de la cabecera.
- Ejemplo práctico 1:
Disponemos de:
Un cliente MPTCP Linux Debian 7.4 con dos tarjetas de red, conectado a dos redes diferentes y con dos gateways.
El tráfico de las dos tarjetas de red del cliente está limitado a 10 Mbps para obtener unas gráficas más fáciles de entender.
El servidor MPTCP es también un Linux Debian Wheezy, con una tarjeta de red y conectado a 100 Mbps.
El tráfico MTPCTP irá sobre ipv4
Todos los hosts reciben ip de un dhcp.
He escogido Debian porque es la única distribución linux cuyo repositorio de multipath-tcp es compatible para 32 bits.
Mi servidor ESXi doméstico no dispone un procesador con extensiones VT para virtualizar 64 bits y no deseaba recompilar el kernel.
Direccionamiento IP:
mptcp-client-eth0 = 10.0.220.2/24 , default gateway = 10.0.220.1
mptcp-client-eth1 = 10.0.221.2/24 , default gateway = 10.0.221.1
mptcp-server = 10.0.222.2/24 , default gateway = 10.0.222.1
Vamos a preparar el cliente.
El procedimiento de instalación sobre linux existe en el site de multipath-tcp.org, pero lo añado para completar el ejemplo:
root@mptcp-client:~# uname -a Linux mptcp-client 3.2.0-4-686-pae #1 SMP Debian 3.2.54-2 i686 GNU/Linux root@mptcp-client:~# lsb_release -a No LSB modules are available. Distributor ID: Debian Description: Debian GNU/Linux 7.4 (wheezy) Release: 7.4 Codename: wheezy
Añadimos las keys del repositorio de multipath
root@mptcp-client:~# wget -q -O - http://multipath-tcp.org/mptcp.gpg.key | apt-key add - OK
Hacemos un copy & paste sobre el terminal (para Debian Wheezy):
cat > /etc/apt/sources.list.d/mptcp.list <<EOF deb http://multipath-tcp.org/repos/apt/debian wheezy main EOF #
Actualizamos e instalamos:
root@mptcp-client:~# apt-get update root@mptcp-client:~# apt-get install linux-mptcp ... se instala ...
Observamos que todavía no está activado porque implica un nuevo kernel, por lo tanto reboot:
root@mptcp-client:~# sysctl -a | grep mptcp kernel.hostname = mptcp-client
Reiniciamos:
root@mptcp-client:~# reboot
Una vez hemos reiniciado, verificamos la versión del kernel y volvemos a comprobar con sysctl si tenemos las nueva directivas habilitadas:
root@mptcp-client:~# uname -r 3.11.10.wheezymptcp root@mptcp-client:~# sysctl -a | grep mptcp kernel.hostname = mptcp-client kernel.osrelease = 3.11.10.wheezymptcp net.mptcp.mptcp_checksum = 1 net.mptcp.mptcp_debug = 0 net.mptcp.mptcp_enabled = 1 net.mptcp.mptcp_ndiffports = 2 net.mptcp.mptcp_path_manager = fullmesh net.mptcp.mptcp_syn_retries = 3
Ahora modificaremos las tablas de rutas.
En mi caso no las he hecho permanentes, pero hay métodos en la documentación (ver referencias al final del post).
Hacemos otro copy & paste sobre el terminal para crear el script rutes.sh :
cat > /bin/rutes.sh <<EOF # This creates two different routing tables, that we use based on the source-address. ip rule add from 10.0.220.2 table 1 ip rule add from 10.0.221.2 table 2 # Configure the two different routing tables ip route add 10.0.220.0/24 dev eth0 scope link table 1 ip route add default via 10.0.220.1 dev eth0 table 1 ip route add 10.0.221.0/24 dev eth1 scope link table 2 ip route add default via 10.0.221.1 dev eth1 table 2 # default route for the selection process of normal internet-traffic ip route add default scope global nexthop via 10.0.220.1 dev eth0 EOF #
Hacemos el script ejecutable y lo ejecutamos para que se modifiquen las tablas de routing:
root@mptcp-client:~# chmod +x /bin/rutes.sh root@mptcp-client:~# rutes.sh
Ahora crearemos un script ( rutes-verify.sh ) para verificar rápidamente las tablas de rutas.
Copy & paste en el terminal:
cat /bin/rutes-verify.sh <<EOF echo -e '\n#### ip rule show ####' ip rule show echo -e '\n#### ip route ####' ip route echo -e '\n#### ip route show table 1 ####' ip route show table 1 echo -e '\n#### ip route show table 2####' ip route show table 2 echo -e '\n EOF #
Igual que anteriormente lo hacemos ejecutable y lo ejecutamos:
root@mptcp-client:~# chmod +x /bin/rutes-verify.sh root@mptcp-client:~# rutes-verify.sh
El resultado esperado es el siguiente:
root@mptcp-client:~# rutes-verify.sh #### ip rule show #### 0: from all lookup local 32762: from 10.0.221.2 lookup 2 32763: from 10.0.220.2 lookup 1 32764: from 10.0.221.2 lookup 2 32765: from 10.0.220.2 lookup 1 32766: from all lookup main 32767: from all lookup default #### ip route #### default via 10.0.220.1 dev eth0 10.0.220.0/24 dev eth0 proto kernel scope link src 10.0.220.2 10.0.221.0/24 dev eth1 proto kernel scope link src 10.0.221.2 #### ip route show table 1 #### default via 10.0.220.1 dev eth0 10.0.220.0/24 dev eth0 scope link #### ip route show table 2#### default via 10.0.221.1 dev eth1 10.0.221.0/24 dev eth1 scope link
- Resultados ejemplo 1:
He realizado un iperf desde el cliente ( 2x enlaces de 10Mbps ) contra el servidor.
El resultado es el esperado, se cursan entre 18 y 19 Mbps usando los 2 links simúltaneamente.
Durante el test, he deshabilitado el interfaz eth1 del cliente desde el switch.
Se observa que se degrada el throughput al 50 %, sobre los 9.4 Mbps pero se manteniene la conexión.
Empezamos el test:
Lanzamos un iperf y se agregan los 10 + 10 Mbps en dos conexiones diferentes.
Una por cada intefaz.
root@mptcp-client:~# iperf -c 10.0.222.2 -t 3600 -i 5 ------------------------------------------------------------ Client connecting to 10.0.222.2, TCP port 5001 TCP window size: 21.0 KByte (default) ------------------------------------------------------------ [ 3] local 10.0.220.2 port 59808 connected with 10.0.222.2 port 5001 [ ID] Interval Transfer Bandwidth [ 3] 0.0- 5.0 sec 10.9 MBytes 18.2 Mbits/sec [ 3] 5.0-10.0 sec 10.6 MBytes 17.8 Mbits/sec [ 3] 10.0-15.0 sec 11.2 MBytes 18.9 Mbits/sec [ 3] 15.0-20.0 sec 11.0 MBytes 18.5 Mbits/sec [ 3] 20.0-25.0 sec 11.1 MBytes 18.7 Mbits/sec [ 3] 25.0-30.0 sec 10.4 MBytes 17.4 Mbits/sec [ 3] 30.0-35.0 sec 8.50 MBytes 14.3 Mbits/sec [ 3] 35.0-40.0 sec 11.0 MBytes 18.5 Mbits/sec [ 3] 40.0-45.0 sec 10.9 MBytes 18.2 Mbits/sec [ 3] 45.0-50.0 sec 10.9 MBytes 18.2 Mbits/sec [ 3] 50.0-55.0 sec 11.2 MBytes 18.9 Mbits/sec [ 3] 55.0-60.0 sec 10.9 MBytes 18.2 Mbits/sec [ 3] 60.0-65.0 sec 11.4 MBytes 19.1 Mbits/sec
El netstat muestra 2 conexiones concurrentes de cada interfaz del cliente ( source ip’s difrerentes ):
root@mptcp-server:~# netstat -tpan | grep iperf tcp 0 0 10.0.222.2:5001 10.0.221.2:37696 ESTABLISHED 3365/iperf tcp 0 0 10.0.222.2:5001 10.0.220.2:59802 ESTABLISHED 3365/iperf
Visualizamos IPTraf:
Deshabilitamos un interfaz del cliente en el switch:
[ 3] 175.0-180.0 sec 11.1 MBytes 18.7 Mbits/sec
[ 3] 180.0-185.0 sec 10.5 MBytes 17.6 Mbits/sec
[ 3] 185.0-190.0 sec 9.38 MBytes 15.7 Mbits/sec
[ 3] 190.0-195.0 sec 5.50 MBytes 9.23 Mbits/sec
[ 3] 195.0-200.0 sec 5.50 MBytes 9.23 Mbits/sec
[ 3] 200.0-205.0 sec 5.50 MBytes 9.23 Mbits/sec
[ 3] 205.0-210.0 sec 5.62 MBytes 9.44 Mbits/sec
[ 3] 210.0-215.0 sec 4.38 MBytes 7.34 Mbits/sec
[ 3] 215.0-220.0 sec 5.62 MBytes 9.44 Mbits/sec
[ 3] 220.0-225.0 sec 5.12 MBytes 8.60 Mbits/sec
[ 3] 225.0-230.0 sec 5.62 MBytes 9.44 Mbits/sec
root@mptcp-server:~# netstat -tpan | grep iperf
tcp 0 0 10.0.222.2:5001 10.0.220.2:59802 ESTABLISHED 3365/iperf
Recuperamos link ( salida parcial de iperf ):
[ 3] 365.0-370.0 sec 5.62 MBytes 9.44 Mbits/sec
[ 3] 370.0-375.0 sec 5.50 MBytes 9.23 Mbits/sec
[ 3] 375.0-380.0 sec 5.12 MBytes 8.60 Mbits/sec
[ 3] 380.0-385.0 sec 5.62 MBytes 9.44 Mbits/sec
[ 3] 385.0-390.0 sec 5.25 MBytes 8.81 Mbits/sec
[ 3] 390.0-395.0 sec 4.38 MBytes 7.34 Mbits/sec
[ 3] 395.0-400.0 sec 10.5 MBytes 17.6 Mbits/sec
[ 3] 400.0-405.0 sec 10.6 MBytes 17.8 Mbits/sec
[ 3] 405.0-410.0 sec 10.9 MBytes 18.2 Mbits/sec
[ 3] 410.0-415.0 sec 10.9 MBytes 18.2 Mbits/sec
[ 3] 415.0-420.0 sec 10.6 MBytes 17.8 Mbits/sec
[ 3] 420.0-425.0 sec 11.2 MBytes 18.9 Mbits/sec
[ 3] 425.0-430.0 sec 10.8 MBytes 18.0 Mbits/sec
- Ejemplo práctico 2:
Vamos a realizar una descarga http de un servidor en internet desde nuestro cliente multipath-tcp.
Como el firewall de salida es un Cisco ASA y además existe un nat de salida, configuraremos un policy-map para que no “dropee” los paquetes multipath-tcp.
En realidad no los “dropea”, lo que haría el firewall sin el policy-map es “sanear” el segmento tcp eliminando los campos que no reconoce, en este caso las opciones multipath-tcp.
Si no hiciéramos esto, el tráfico saldría igualmente atravesando el firewall y el nat, pero no usaríamos multipath-tcp.
Como ya hemos comentado anteriormente, multipath-tcp provee compatibilidad hacia atrás con tcp y por lo tanto es capaz de comunicar a lo hosts sin sus extensiones tcp.
Esto es, la conexión sería tcp estándard.
- Configuración del firewall Cisco PIX/ASA:
La siguiente configuración está modificada respecto a la propuesta por la documentación oficial de Cisco.
El motivo es que Cisco propone usar un service-policy a nivel global diferente al que por defecto incorpora un firewall Cisco PIX/ASA.
En mi ejemplo conservamos el service policy original porque si tenemos QoS, shaping u otras configuraciones afectadas dejarían de funcionar como esperamos.
En cualquier caso, revisa tu configuración.
tcp-map multipath-tcp tcp-options range 30 30 allow class-map tcp-normal match any policy-map global_policy class tcp-normal set connection advanced-options multipath-tcp service-policy global_policy global
Lanzamos un wget para probarlo desde nuestro cliente:
root@mptcp-client:~# wget http://multipath-tcp.org/snapshots/mptcp_2014_02_06.tar.gz --2014-02-23 15:04:01-- http://multipath-tcp.org/snapshots/mptcp_2014_02_06.tar.gz Resolving multipath-tcp.org (multipath-tcp.org)... 130.104.230.45, 2001:6a8:3080:1:216:3eff:fec5:c815 Connecting to multipath-tcp.org (multipath-tcp.org)|130.104.230.45|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 116401402 (111M) [application/x-gzip] Saving to: `mptcp_2014_02_06.tar.gz.4' 13% [===========>
Observemos algunas tramas y una cabecera tcp de la captura con Wireshark:
En verde, la ip del cliente en la interfaz eth0 inicia el clásico 3-way handshake tcp.
En rojo, la ip del cliente en la interfaz eth1 también inicia el 3-way handshake ( segundo flow ).
He seleccionado las primeras tramas más importantes.
En todas las tramas hay el campo options que incluye multipath tcp, pero en esta captura sólo vemos las correspondientes a la trama 6 porque es la que tenía seleccionada.
Cabe destacar también el cuadro azul donde se observan el token ( identificador de conexión ) y el sender’s random number para evitar ataques replay.
- Referencias y links de interés:
http://multipath-tcp.org/
http://tools.ietf.org/html/rfc6824
http://blogs.citrix.com/2013/05/28/maximize-mobile-user-experience-with-netscaler-multipath-tcp/
https://devcentral.f5.com/articles/multipath-tcp-mptcp
http://www.cisco.com/c/en/us/support/docs/ip/transmission-control-protocol-tcp/116519-technote-mptcp-00.html
http://arstechnica.com/apple/2013/09/multipath-tcp-lets-siri-seamlessly-switch-between-wi-fi-and-3glte/
http://multipath-tcp.org/pmwiki.php?n=Main.50Gbps
5 Comments
esto es muy interesante… quiero saber mas… es un buen aporte…
Buenos días,
¿cómo creaste el server?
Otra máquina con mptcp instalada supongo, ¿usaste ipref -s?
Hola,
primero disculpa que no haya contestado antes, no me activé alertas de cuándo hay un comentario pendiente…
La forma de instalación la puedes encontrar en:
http://multipath-tcp.org/pmwiki.php/Users/HowToInstallMPTCP?
Gracias por participar en el blog!
Yo querria hacerte una pregunta. Estoy utilizando cacti para monitorizacion de redes y he visto en tu post que la grafica de mptcp tienes agregado varias conexiones en una sola grafica .. esto yo no se realizarlo en cacti … me podrías echar una mano?
Gracias
Hola,
primero disculpa que no haya contestado antes, no me activé alertas de cuándo hay un comentario pendiente.
Sobre la agregación de gráficas en cacti, te recomiendo el plugin Aggregate de Cacti: http://docs.cacti.net/plugin:aggregate
Gracias por participar en el blog.