4 puntos por GN⁺ 2024-01-17 | 1 comentarios | Compartir por WhatsApp
  • Speedbump es un proxy TCP escrito en Go que simula condiciones de demora al agregar latencia de red variable al tráfico TCP que se enruta a través del proxy
  • A la latencia base se le pueden sumar componentes de latencia con forma de onda sinusoidal, diente de sierra, cuadrada y triangular, y se pueden combinar varios componentes al mismo tiempo
  • El ejemplo muestra una configuración que hace proxy del tráfico dirigido a localhost:80 en el puerto 2000, aplicando una demora base de 100ms, amplitud sinusoidal de 100ms y un período de 1m
  • La instalación puede hacerse descargando binarios precompilados por release, compilando desde el código fuente con go build, o ejecutando la imagen de contenedor kffl/speedbump
  • Además del CLI, también puede usarse como biblioteca mediante el paquete lib de Go, con parámetros para ajustar el tamaño del búfer, el tamaño de la cola de demora, el nivel de logs, el host de escucha y el puerto

Proxy para simular latencia TCP

  • Speedbump es un proxy TCP escrito en Go y puede simular latencia de red variable
  • El destino del proxy se especifica con el argumento <destination> del CLI, indicado con el formato host:post
  • El funcionamiento básico consiste en hacer proxy del tráfico TCP hacia el destino mientras se agrega la latencia configurada

Instalación y formas de ejecución

  • La forma más sencilla de instalación es descargar los binarios precompilados que se adjuntan automáticamente en Assets de cada release
  • Para compilar desde el código fuente, se clona el repositorio y luego se ejecuta go build
  • Para ejecutarlo como contenedor, se puede usar la imagen kffl/speedbump

Ejemplo básico de uso

  • Puede escuchar en el puerto 2000 y hacer proxy del tráfico TCP hacia localhost:80, aplicando una latencia base de 100ms, amplitud sinusoidal de 100ms y período de 1m
    • Esta configuración genera una latencia adicional máxima de 200ms y una latencia adicional mínima de 0
    • El ejemplo de ejecución es speedbump --latency=100ms --sine-amplitude=100ms --sine-period=1m --port=2000 localhost:80
  • La misma configuración también puede ejecutarse con la imagen de contenedor
    • El ejemplo es docker run --net=host kffl/speedbump:latest --latency=100ms --sine-amplitude=100ms --sine-period=1m --port=2000 localhost:80
  • También se puede configurar un componente de latencia en diente de sierra
    • El ejemplo usa una latencia base de 300ms, amplitud de diente de sierra de 200ms, período de 2m, puerto 2000 y destino localhost:80
    • El comando es speedbump --latency=300ms --saw-amplitude=200ms --saw-period=2m --port=2000 localhost:80

Combinación de componentes de latencia

  • Speedbump puede aplicar varios componentes de latencia al mismo tiempo
  • El README incluye un ejemplo de gráfico de latencia que combina diente de sierra y onda sinusoidal

Argumentos del CLI y uso como biblioteca

  • speedbump --help muestra el uso con el formato speedbump [<flags>] <destination>
  • Las principales opciones de red son las siguientes
    • --host: IP o nombre de host donde escuchará; si no se especifica, se enlaza a todas las interfaces de red
    • --port: puerto de escucha; el valor predeterminado es 8000
    • --buffer: tamaño del búfer usado para lecturas TCP; el valor predeterminado es 64KB
    • --queue-size: tamaño de la cola de demora que almacena los búferes leídos; el valor predeterminado es 1024
  • También ofrece valores predeterminados y opciones de forma de onda para la latencia
    • --latency: latencia base que se agrega al tráfico en proxy; el valor predeterminado es 5ms
    • --sine-amplitude, --sine-period: amplitud y período de la latencia sinusoidal
    • --saw-amplitude, --saw-period: amplitud y período de la latencia en diente de sierra
    • --square-amplitude, --square-period: amplitud y período de la latencia cuadrada
    • --triangle-amplitude, --triangle-period: amplitud y período de la latencia triangular
  • También incluye opciones operativas
    • --log-level: nivel de logs; los valores posibles son DEBUG, TRACE, INFO, WARN, ERROR
    • --version: muestra la versión de la aplicación
  • Speedbump también puede usarse como biblioteca de Go mediante el paquete lib
  • La licencia es Apache 2.0 License

1 comentarios

 
GN⁺ 2024-01-17
Opiniones en Hacker News
  • Estuve buscando algo parecido para probar varias implementaciones de ActivityPub con distintos tamaños y condiciones de red, pero resultó que ya tenía todo lo necesario instalado en mi máquina con tc
    En mi distribución venía incluido en el paquete iproute2, y también hay una explicación aquí: https://wiki.archlinux.org/title/advanced_traffic_control
    Para agregar latencia a una interfaz específica, se puede ejecutar algo como tc qdisc add dev eth0 root netem delay 100ms
    Es fácil de usar, funciona bien incluso en contenedores Docker, permite aplicar condiciones como latencia, pérdida y duplicación de paquetes, y probablemente ya lo tengas instalado

    • tc/netem/tbf son realmente buenos. Armé una GUI en Python sencilla encima de eso y la corrí en una Pi dentro de una carcasa con pantalla táctil; era una cajita negra con opciones como “paquetes descartados: [0%] [1%] [10%] [50%] / corrupción de paquetes: ...”, y a los clientes les impresionaba bastante
      Me sorprende que no se vean mucho frontends parecidos como productos comerciales de hardware; si no se me escaparon en las búsquedas, parece que no existen en el mercado
    • La desventaja de tc es que aplicarlo a paquetes entrantes es algo raro y complicado
      Hace tiempo hice mi propio emulador para imitar una terminal satelital comercial específica. Esa terminal acumulaba paquetes en una cola y, al llegar a cierto umbral o superar un límite de tiempo, los soltaba en bloque; además intentaba reducir la latencia reordenando “amablemente” los paquetes pequeños hacia el frente de la cola, pero al stack TCP eso le desagradaba muchísimo
    • Lo bueno de speedbump es que permite ajustar las condiciones de falla con el tiempo. tc no puede hacer eso
      Podría ser bastante útil para simular los efectos del clima en enlaces satelitales/RF que cambian con el tiempo
  • Esto era exactamente lo que Netflix había creado, y se llamaba latency monkey
    Descubrimos que determinar si un servicio dependiente está “lento” es mucho más difícil que determinar si está “no disponible”, así que era una forma importante de probar cómo manejan los servicios la lentitud y los problemas de red
    La implementación era muy simple: descartaba paquetes en una proporción configurable, lo que forzaba retransmisiones, de modo que del otro lado los paquetes llegaban con retraso y desordenados
    Al final encontramos muchos problemas en el código de manejo de errores relacionado con el acceso a la red

  • Creo que todo ingeniero de software que haga aplicaciones interactivas de internet debería usar herramientas así en su trabajo diario. No solo para TCP, también hace falta QUIC, e idealmente todo UDP para cubrir incluso DNS
    Estoy convencido de que el 90% de la hipertrofia de las aplicaciones web desaparecería si quienes las crean no usaran únicamente entornos de cómputo tipo Cadillac chapado en oro

  • En entornos donde la conexión de red se corta de forma intermitente, como en situaciones de ayuda ante desastres, muchas apps funcionan pésimo
    Si más desarrolladores de apps probaran simulando conectividad intermitente, eso podría ayudar a otros
    De “Toxiproxy is a framework for simulating network conditions” (2021) https://news.ycombinator.com/item?id=29084277#29088775:

    Muchas apps no tienen, por ejemplo, una función de “dejar pendiente en la bandeja de salida” como la que uno esperaría en un cliente de correo

    • [ ] ¿Alguien podría crear un conjunto de ‘mutadores de casos de prueba’ de toxiproxy de referencia que simulen problemas comunes de conectividad en #DisasterRelief?
    • Lo que más detesto es cuando no llenan el búfer antes de enviar paquetes. Entonces, en una mala conexión a internet —es decir, un entorno con paquetes descartados y alta latencia que provoca retransmisiones TCP— de pronto solo obtienes 120 kps
      Porque solo se están enviando paquetes de 50 bytes y 1 de cada 10 se pierde. Mientras tanto, un hilo del servidor no está haciendo ningún trabajo útil
  • En Mac se puede hacer lo mismo solo con herramientas integradas

    # Setup pipe  
    sudo dnctl pipe 1 config bw 1Kbit/s delay 800
    
    # Setup matching pf rule  
    echo "dummynet out proto tcp from any to 127.0.0.1 port 11211 pipe 1" | sudo pfctl -f -
    
    # Turn on firewall  
    sudo pfctl -e
    
    # Test  
    time nc -vz 127.0.0.1 11211  
    Connection to 127.0.0.1 port 11211 [tcp/*] succeeded!  
    nc -vz 127.0.0.1 11211 0.01s user 0.00s system 0% cpu 1.333 total  
    
    • Dummynet y estas funciones vienen de FreeBSD, donde existen desde hace mucho. Hace más de 15 años hice pruebas de pérdida de paquetes con esto y funcionaba bien
  • Hay un proyecto que lleva un tiempo inactivo, pero cuyo nombre lo dice casi todo: https://github.com/tylertreat/comcast

  • Hace poco intenté simular una red lenta en Mac y encontré Network Link Conditioner, que está bastante bien. No hace falta configurar algo como un proxy
    Hay que instalarlo desde las herramientas adicionales de Xcode
    https://nshipster.com/network-link-conditioner/

  • También vale la pena ver la excelente herramienta toxiproxy de Shopify: https://github.com/Shopify/toxiproxy
    También es una muy buena forma de probar una biblioteca de networking que uno mismo esté implementando, porque el stack debería poder manejar correctamente la mayoría de las situaciones adversas
    La idea de la ‘ingeniería del caos’ es genial

    • Yo también busqué toxiproxy al principio, pero el modelo cliente-servidor no me servía, y speedbump encajaba perfecto con mi caso de uso: simular latencia HTTP
      Estoy desarrollando una barra de progreso para un crawler web, y al probar en localhost todo va demasiado rápido como para saber si hay algún problema
      Con speedbump basta ejecutar podman run --net=host kffl/speedbump:latest --latency=1s --port=8001 localhost:8000 y probar el crawler en http://localhost:8001
      Es una herramienta limpia
  • Hay una herramienta parecida que he usado en Windows
    https://jagt.github.io/clumsy/

    • La usé hace unos 10 años para probar varias condiciones de red intercontinentales, y los resultados coincidían bien con la realidad. La recomendaría
    • Se ve genial, pero por las capturas de pantalla parece más una aplicación a nivel de todo el sistema con filtros, no por adaptador
  • FreeBSD también tiene dummynet como parte de ipfw, que permite inyectar latencia, límites de ancho de banda, tamaño de cola y pérdida de paquetes. Es la misma función que existe en MacOS

    • ¿Es como tc en Linux?