9 puntos por GN⁺ 2026-01-23 | 1 comentarios | Compartir por WhatsApp
  • Se descubrió un caso en el que, dentro de una sesión SSH, se transmitían cientos de paquetes con una sola pulsación de tecla, y se rastreó la causa
  • El análisis con tcpdump mostró que la mayoría de los paquetes consistían en mensajes repetidos de 36 bytes, generados aproximadamente cada 20 ms
  • La causa fue la función de “ofuscación del timing de las pulsaciones” (keystroke timing obfuscation) añadida a SSH en 2023, que envía múltiples paquetes “chaff” (SSH2_MSG_PING) para ocultar el momento en que el usuario escribe
  • Al desactivar esta función o modificar el servidor para que no anuncie la extensión [email protected], el uso de CPU y el ancho de banda se redujeron a menos de la mitad
  • Es un caso que muestra cómo una función de seguridad de SSH puede convertirse en una carga importante en aplicaciones donde el rendimiento en tiempo real es crítico (por ejemplo, juegos)

Detección del problema

  • Mientras se probaba la TUI de un juego de alto rendimiento que se ejecutaba a través de SSH, se confirmó que incluso una sola pulsación de tecla generaba 270 paquetes
    • Según tcpdump, el 66% eran mensajes de 36 bytes, el 33% eran TCP ACK y el resto correspondía a una pequeña cantidad de otros datos
    • En promedio se transmitían 90 paquetes por segundo, con intervalos de unos 11 ms
  • Durante las pruebas, el servidor quedó mal configurado para enviar solo el mensaje “your screen is too small”, y en ese momento el uso de CPU y de ancho de banda se redujo a la mitad
    • Como no debería haberse transmitido información del juego, el uso de CPU tendría que haber estado cerca de 0%, pero seguía alrededor del 50%
    • Esto llevó a plantear la posibilidad de un overhead de comunicación propio de SSH

Proceso de investigación

  • Se comparó el tráfico SSH en funcionamiento normal y en estado de error usando tcpdump
    • Incluso en el estado de error, los paquetes de 36 bytes seguían apareciendo cada 20 ms
    • El mismo patrón también se observó en el cliente SSH por defecto de macOS
  • Al analizar el archivo pcap con Claude Code
    • De un total de 413,703 paquetes, el 66% eran de 36 bytes y el 34% eran ACK de 0 bytes
    • El cliente SSH estaba generando activamente los paquetes

Causa raíz

  • En el log de depuración de SSH (ssh -vvv) apareció el siguiente mensaje
    obfuscate_keystroke_timing: starting: interval ~20ms
    obfuscate_keystroke_timing: stopping: chaff time expired (101 chaff packets sent)
    
    • El intervalo de 20 ms y las decenas o más de cien paquetes chaff coincidían con el patrón observado en la práctica
  • La causa era la función de ofuscación del timing de las pulsaciones añadida a SSH en 2023
    • Para evitar que se exponga el patrón de velocidad al teclear del usuario, envía paquetes “chaff” aleatorios
    • Es útil para la seguridad, pero en entornos donde la latencia es importante puede generar una carga excesiva

Solución

  • En el cliente se puede desactivar la función con la opción ObscureKeystrokeTiming=no
    • Tras aplicarla, el uso de CPU y de ancho de banda se redujo notablemente, mientras la transmisión de datos siguió funcionando con normalidad
  • Como respuesta del lado del servidor, se eliminó de la biblioteca SSH de Go el anuncio de la extensión [email protected]
    • Tras revertir el commit relacionado y hacer pruebas, se obtuvo lo siguiente
      • Uso de CPU 29.9% → 11.6% ,
        llamadas al sistema 3.10s → 0.66s,
        operaciones criptográficas 1.6s → 0.11s,
        ancho de banda 6.5Mbit/s → 3Mbit/s
    • El rendimiento mejoró en más de un 50%

Experiencia de depuración con ayuda de LLM

  • Usando Claude Code para automatizar el análisis de tcpdump y tshark, se pudo acotar rápidamente la causa del problema
    • Al observar en tiempo real la ejecución de los comandos, fue posible mantener un modelo mental del proceso
  • También se experimentaron diferencias entre modelos, como cuando ChatGPT evaluó incorrectamente el comportamiento de SSH como “normal”
  • Aunque los LLM no sustituyen todo el proceso de resolución de problemas, mostraron alta eficiencia como herramienta auxiliar de análisis
  • Es un caso de resolución de un problema complejo de rendimiento de red combinando el razonamiento humano con el análisis de un LLM

1 comentarios

 
GN⁺ 2026-01-23
Comentarios de Hacker News
  • Me da un poco de miedo hacer un fork de la biblioteca crypto de Go
    Estoy pensando cómo mantener segura mi pequeña corrección
    En realidad, creo que una función así debería integrarse upstream como una opción de la biblioteca SSH
    En entornos no confiables, enviar paquetes de chaff (ruido) como valor predeterminado suena bien, pero muchas veces también se quiere ahorrar ancho de banda

    • Controlarlo de una manera que no publicita la función es un enfoque demasiado inestable
      La solución correcta sería agregar una opción para que el servidor pueda indicarle al cliente que “no hace falta”, y que el cliente pueda aceptarlo o advertirlo
    • De hecho ya existe un comportamiento parecido
      Solo se aplica en sesiones TTY, y el cliente puede desactivarlo
      Solo que este caso es una situación excepcional donde el servidor ya sabe de antemano que la conexión no es importante
      En la mayoría de los casos, el cliente espera que se respete la configuración ObscureKeystrokeTiming
    • Aun así, creo que es probable que rechacen este cambio
      La biblioteca crypto es una base de código con opiniones muy fuertes, al punto de que ni siquiera te deja cambiar el orden de las cipher suites de TLS
    • Incluso en entornos confiables existen amenazas
      Esto parece un caso de uso muy específico de SSH
      Si se expone demasiado, puede terminar en una situación de “configúralo y olvídalo” que debilite la seguridad
    • Hubo una época en la que usábamos un ZX80 con 1 KB de RAM
      También me tocó comunicarme con módems de 1200 bps, y los módems de 56K en realidad eran prácticamente una exageración
      Hacia 1994 trabajaba en una academia militar del Reino Unido y conocí la WWW por primera vez, pero en ese momento pensé: “qué floja”
      Viéndolo ahora, de verdad sorprende cómo cambian los tiempos
  • No conocía esta función de ofuscación, me pareció interesante
    Al depurar el comportamiento de SSH, también es buena idea parchear el cipher None para ver directamente el contenido de los paquetes
    Si se trata de un juego de terminal donde la seguridad no importa y el rendimiento sí, hasta valdría la pena considerar usar telnet

  • No sabía que SSH hacía esto
    Entiendo por qué viene activado por defecto, pero en mi entorno probablemente convenga desactivarlo

    1. Casi nunca escribo secretos directamente por SSH
    2. No hay razón para que un atacante de nivel estatal esté sniffing mis pulsaciones
    3. La conexión es intercontinental, así que ahorrar ancho de banda es importante
      Así que pienso poner ObscureKeystrokeTiming=no. ¿Hay alguna razón por la que no debería hacerlo?
    • Tener una postura de seguridad optimista es peligroso
      (1) No siempre es fácil distinguir cuándo una persona está escribiendo un secreto, y toda la actividad puede analizarse por patrones
      (2) Este es un ataque posible incluso a nivel de laboratorio universitario — ver el paper de USENIX y este caso de investigación
      (3) En un internet dominado por tráfico de video, renunciar a seguridad por ahorrar unos pocos bytes de pulsaciones no tiene sentido
    • Un secreto que se escribe con frecuencia en conexiones tty SSH es la contraseña de sudo
      Si un atacante analiza el timing de las pulsaciones, podría inferir tanto el comando como el patrón de la contraseña cifrada
      Claro, como la clave de sesión cambia cada vez, descifrarlo sería difícil, pero la posibilidad existe
      Yo también copio y pego la mayoría de mis contraseñas desde un gestor de contraseñas
    • No puedes estar seguro de que cualquier texto plano filtrado no le sirva de nada a un atacante
      La mayoría de la gente siente que no pasa nada aunque desactive funciones de seguridad de SSH, pero eso solo significa que ha tenido suerte
      Si de verdad necesitas rendimiento, usa Telnet; si de verdad necesitas seguridad, conviene una combinación de ContainerSSH + OAuth2
  • En 2004 hice investigación para inferir comandos analizando la latencia entre pulsaciones en sesiones SSH
    Véase este análisis de la época
    El parche de 2023 finalmente vino a resolver ese problema

    • Recuerdo que en la conferencia de hacking HAL2001 Dug Song y Solar Designer presentaron análisis de timing de SSH
      Material de la presentación
      De verdad pasa muy rápido el tiempo
  • No estoy seguro de que Claude haya ayudado de verdad en la depuración
    El autor ya sabía hacia dónde iba, y Claude solo parecía seguirle la corriente
    Que Claude diga cosas como “Holy Cow!” me resulta un poco molesto

    • Aun así, si le ayudó a ordenar sus ideas como en Rubber Duck Debugging, ya tuvo valor
      A mí también me pasa que al depurar cómo funciona un sistema con Claude, aunque no me dé una respuesta directa, sí me ayuda a ordenar la comprensión y mantener la motivación
      Wiki de Rubber Duck Debugging
    • Claude es mucho más rápido que yo para extraer campos de pcap o procesarlos con awk
    • La IA es muy buena para detectar personalidad en el texto
      Si el autor puso en su blog una reacción como “holy cow”, parece que Claude leyó bien el ambiente
    • Quizá no fue buena idea darles personalidad a las herramientas de desarrollo
  • Usar TCP_CORK permite reducir la cantidad de paquetes sin introducir latencia
    Desactivar TCP_NODELAY también es una opción, pero el costo es más latencia

    • No conocía TCP_CORK, está interesante
      Al hacer cork en el socket, el kernel guarda los datos en buffer y los envía cuando se hace uncork o se llega al MSS
      Es decir, agrupa paquetes antes de enviarlos
      Referencia
    • No conocía TCP_CORK, pero de verdad parece útil
      Seguiría recibiendo ping, pero quizá podría reducir la cantidad de envíos de pong
      Ya probé TCP_NODELAY, pero aumentó demasiado la latencia y no me sirvió para mi juego
      Publicación anterior en HN
    • Pero como los paquetes de chaff se envían cada 20 ms, no está claro si TCP_CORK podría agruparlos
      Con fines de ofuscación, probablemente no se pueda hacer coalescing de latencia
  • La expresión “The smoking gun!” me dio risa
    No soy hablante nativo de inglés, pero Claude la usa seguido y la aprendí así
    Ahora de verdad se está propagando como muletilla

  • Me decepciona la dependencia de los LLM
    Esto probablemente se habría resuelto más rápido viendo una captura de paquetes en Wireshark
    El dissector de SSH está bastante maduro

    • A mí tampoco me encantan los LLM, pero si miras paquetes SSH en Wireshark, la mayoría son solo paquetes cifrados, así que no obtienes información muy útil
      Incluso si capturas una sola pulsación con tcpdump, salen cientos de paquetes cifrados
      Al final, gracias al LLM el autor aprendió algo interesante y lo compartió, así que tuvo sentido
    • El dissector de SSH no es perfecto
      Después del mensaje NEWKEYS ya no puede parsear, e incluso parcheando cifrado none no interpreta completamente el flujo
      Hay margen de mejora
    • La actitud de “solo había que verlo en Wireshark” suena a gatekeeping
      Aprender usando herramientas también tiene valor
    • SSH es, desde su nombre, un protocolo de seguridad
      Con una simple captura de paquetes es difícil obtener información significativa
    • El autor no conocía un analizador de paquetes SSH, y en cambio usó una herramienta general (LLM)
      No veo por qué eso sería algo lamentable
  • En 2023 SSH agregó una función de ofuscación del timing de pulsaciones
    Como es posible inferir caracteres por la velocidad de tecleo, SSH mezcla paquetes de chaff para que el atacante no pueda distinguirlos
    Pero esto parece un enfoque equivocado
    Si de verdad se quisiera, bastaría con enviar todas las pulsaciones a intervalos de 50 ms

    • Un retraso de 50 ms probablemente se sentiría muy desagradable al escribir
    • No queda claro si con enviar a intervalos de 50 ms te refieres a cambiar 20 ms por 50 ms, o a un envío continuo a intervalos fijos
      La implementación actual agrupa en unidades de 20 ms, pero deja de enviar chaff después de cierto tiempo sin actividad
  • El punto central de SSH es la seguridad, pero si no necesitas seguridad, queda la duda de por qué usar SSH
    Por ejemplo, netcat(nc) viene instalado por defecto en la mayoría de las plataformas

    • Que “la seguridad es la prioridad número uno” no significa que eso sea todo
      En SSH también hay otras consideraciones como rendimiento y comodidad
      El autor solo dijo que no necesita la función de ofuscación de pulsaciones (privacy)
      Puede seguir queriendo cifrado e integridad
      O sea, conservar la mayor parte de las funciones de seguridad de SSH y desactivar solo una parte
    • Ahora Windows también incluye SSH, así que decir que “todas las plataformas tienen nc” no es exacto