Multipath TCP – Introducción y prueba en laboratorio

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

multipath-tcp-ejemplo-1-mini

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.

cacti-captura-multipath-tcp-3-graphs

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:

iptraf-multipath-tcp

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.

wireshark-mutipath-tcp-join-mini

  • 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

  • Juan Jose
    06/06/2014 - 4:38 pm | Permalink

    esto es muy interesante… quiero saber mas… es un buen aporte…

  • Delia
    24/10/2016 - 10:42 am | Permalink

    Buenos días,
    ¿cómo creaste el server?

    Otra máquina con mptcp instalada supongo, ¿usaste ipref -s?

  • Silvia
    15/12/2016 - 10:57 am | Permalink

    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

    • 05/01/2017 - 12:04 pm | Permalink

      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.

  • Leave a Reply

    Your email address will not be published. Required fields are marked *