Desafio Networking [el problema]
Reading time: 27 – 44 minutesEscenario
Se dispone de un dispositivo de hardware con un linux embedded al que no se puede acceder ya que el fabricante no lo facilita, se ha intentado acceder pero no hemos sido capaces de acceder ni con nuestros medios ni con los de una importante empresa de electrónica. Creemos que el kernel es un 2.4.X por lo que observamos. El dispositivo tiene una pantalla y su finlidad es mediante un protocolo propietario y un protocolo de transporte de ficheros (FTP) descargar una playlist para reproducir en la pantalla.
A través de red se conecta al servidor del fabricante de donde recoje una playlist y unos contenidos multimedia. Escencialmente usa los puertos:
- TCP/8889 (protocolo de control del fabricante) va en ‘plain text’ ya le hemos hecho la ingenieria inversa.
- FTP en modo pasivo
Con el servidor del fabricante descarga el 99% de la veces correctamente y sin problemas. En el fichero adjunto ‘korea-ok.cap’ si lo examinais podreis ver que todo se desarrolla perfectamente. La IP privada que podeis ver es del dispositivo en la LAN y a través de una LMDS se conecta a Korea a la IP: 210.114.220.180, si os fijais el fabricante usa como servidor FTP un ‘Serv-U’ para Windows.
Problema
Se ha implementado el protocolo propietario del fabricante con Python y funciona perfectamente, el problema es al hacer la descarga por FTP. El dispositivo se conecta a nuestro servidor FTP y de forma completamente aleatoria cierra la transmisión sin motivo aparente y se reinicia el dispositivo. Esto siempre pasa mientras se esta haciendo una conexión FTP-control (21/tcp) o FTP-data (puerto aleatorio del ftp pasivo/tcp).
En el fichero ‘cwd-fail.cap’ se puede ver uno de los típicos fallos que tiene el dispositivo al intentar descargar a un servidor FTP local (en este caso un proftpd en una Gentoo). Concrectamente al mandar el comando FTP ‘CWD’ el dispositivo decide cerrar la conexión y no seguir con la descarga. Después de varios intentos se reinicia. Para no perderos con los paquetes he dejado en la captura sólo el socket que tiene el problema.
Para no despistar recordar que esto no tiene porqué pasar en el canal de FTP-control puede pasar también en un FTP-data, puede pasar al 1% de descarga del fichero, al 30%, 50%, 98%… es completamente aleatorio.
Para tener más ejemplos de errores se adjunta el fichero ‘local-fail.cap’ donde se puede ver como se da un error igual al anterior pero ahora en el canal de datos de FTP. Concretamente podeis ver como se cierra el socket en el paquete 916 sin motivo apararente. Comentar que los errores de checksum de TCP no son relevantes ya que son debidos a que la tarjeta de red no estaba como sigue:
# ethtool -k eth0
Offload parameters for eth0:
rx-checksumming: off
tx-checksumming: off
scatter-gather: off
tcp segmentation offload: off
udp fragmentation offload: off
generic segmentation offload: off
En otras pruebas se han hecho con los parametros comentados y el error es el mismo. A pesar de que ya no aparecen las alertas por ‘checksum error’. Si se cree vital tener una captura sin los errores de checksum no hay problema en hacerla. Pero después de meses de pruebas esta claro que esto no es relevante.
Para demostrar que el comportamiento es aleatorio a continuación se adjunta un fichero ‘local-ok.cap’ con la captura de una sesión en el serividor FTP local que ha funcionado perfectamente. Se puede observar en el paquete: 18975 que se descarga bien el contenido de un fichero, concretamente un fichero .mpg, con este fichero finaliza todo el traspaso de datos correctamente.
Hardware y soft probado
Se han hecho infinidad de pruebas y de combinaciones:
5 servidores distintos:
- 1 debian con kernel 2.6.24.5-grsec-xxxx-grs-ipv4-64 en el proveedor ovh.es (100Mpbs simétricos sin restricciones), servidor FTP proftpd puerto 2090/tcp
- 1 debian con kernel 2.6.18-5-686 proveedor jazztel sin fw, ni restricción de ningún tipo 100Mbps simétricos contra internet y servidores FTP en el puerto 21 pure-ftpd y en el puerto 2090 proftpd.
- 1 ubuntu con kernel 2.6.24-16-server proveedor jazztel con fortinet como fw en modo transparente, proftpd en puerto 2090.
- 1 gentoo con kernel 2.6.25-gentoo-r5 en red local con proftpd en puerto 2090.
- 1 windows xp virtualizado con vmware workstation 6 sobre gentoo con un servidor FTP Serv-U, la tarjeta de red virtual en modo bridget con la del sistema operativo host.
el comportamiento es el mismo con todas la combinaciones
Intuición de solución
Jugando con los parámetros del kernel de TCP (/proc/sys/net/ipv4) se consiguen hacer cambios de comportamiento en el error. Por ejemplo, se han hecho pruebas con:
tcp_adv_win_sacle = 0,1,2
tcp_allowed_congestion_control = cubic, bic, reno, etc.
tcp_base_mss = 512, 1024, 1500
tcp_dsack = 0,1
tcp_ecn = 0,1
tcp_fack = 0,1
tcp_sack = 0,1
tcp_syncookies = 0,1
tcp_timestamps = 0,1
tcp_workaround_signed_windows = 0,1
tcp_window_scaling = 0,1
infinidad de valores y combinaciones probadas en:
tcp_mem
tcp_moderate_rcvbuf
tcp_mtu_probing
tcp_rmem
tcp_tso_win_divisor
tcp_wmem
También se han hecho pruebas limitando el ancho de banda, y con algunos otros parámetros de kernel que ahora no recuerdo. Se ha probado de opimitzar los servers para rendir al máximo, al mínimo, por defecto… etc.
Lo que se consigue con todo esto es conseguir que algunas veces se haga la descarga, pero no se consigue afianzar patrones de forma feaciente, es decir, a menudo se sigue cerrando la conexión TCP.
FAQ de obviedades
- Es obvio que el firmware del dispositivo esta mal hecho, pero esto no se puede tocar.
- El dispositivo se puede configurar via una compact flash, donde se guarda un fichero de configuración, un fichero binario compilado para ARM y el contenido multimedia que se va descargando.
- Se ha intentado hablar mil veces con el fabricante pero es como hablar con una pared, a parte los técnicos no hablan inglés, sólo coreano. Increible, no?
- El problema lo tiene el stack TCP del dispositivo o algún otro elemento similar. Este es el que cierra la conexión!!! no se puede mantener la conexión abierta des del servidor cuando el dispositivo la ha cerrado, lo único que se puede hacer es evitar que el cliente la cierre. El problema es como.
- Si! el server del fabricante descarga bien via FTP en el 99% de los casos. Este es el gran probleam, parece tonta la pregunta pero me la han hecho como 20 veces, así que merecia estar aquí.
Ficheros
Los ficheros de los que se habla en este correo de pueden descargar de:
- http://oriolrius.cat/downloads/korea-ok.cap
- http://oriolrius.cat/downloads/cwd-fail.cap
- http://oriolrius.cat/downloads/local-fail.cap
- http://oriolrius.cat/downloads/local-ok.cap
Desafio
El entorno de laboratorio lo tengo montado en la oficina, esta abierta 24×7 para quedar conmigo para hacer pruebas in-situ. Obviamente responderé todo lo que sea online y orientaré con lo que pueda y más.
Este problema lo arrastro desde hace unos 4 meses y llevo casi 4 dias sin vida, sólo obsesionado buscando la solución pero no hay manera de ver la luz.
No dispongo de muchos recursos, debido a que ya he perdido muchísmo dinero buscando la solución durante todo este tiempo, pero bajo resultados se recompensará tanto como sea posible a la mente privilegiada que consiga dar con la solución.
Ya tengo solución
Después de darle vueltas al tema de momento no contaré las varias soluciones que a dia de hoy ya he enontrado al problemón. Así pue aprovecharé el problema para lanzar el podcast 1×11 describiendo con todo detalle el problema y dando algunas pistas de como llegar a la solución. Quizá a nadie le pique tanto la curiosidad como para seguir la solución con este detalle pero de esta forma mantengo un poco la intriga y si alguien realmente necesita saber la solución sin seguir el culebrón sólo tiene que mandarme un correo privado y se lo contaré. Para hacer boca deciros que la intuición de solución que tenia no era mala.