bambouville

Bloqueos de MTU en WSL

Un host WSL2 es la única configuración en la que una sesión conecta con normalidad y luego, sencillamente, se detiene, sin error en ninguno de los dos extremos. Casi nunca es cosa de SSH ni de Tessera: es la MTU del adaptador virtual tras el que se sitúa WSL2. Cuando Tessera observa el bloqueo característico al conectar, muestra una tarjeta ámbar de posible problema de MTU con WSL2 / Tailscale que enlaza aquí.

Síntomas

  • La sesión conecta, aparece el prompt y los comandos cortos funcionan bien.
  • Todo lo que envía una ráfaga grande se congela: un cat de un archivo largo, un ls ancho, un redibujado completo de tmux, una transferencia en el panel de archivos.
  • Nada informa de un fallo. La sesión simplemente deja de moverse. Volver a conectar funciona, y luego se atasca otra vez con el mismo tipo de salida.
  • El mismo host por mosh se comporta mejor que por ssh.

Si la conexión no llega siquiera a un prompt, el mismo fallo puede estar tragándose el intercambio de claves SSH, que ya de por sí es grande. La prueba de abajo sigue valiendo.

Por qué ocurre

WSL2 se ejecuta tras un conmutador virtual de Hyper-V, y su eth0 arranca con una MTU de 1500. Cuando el equipo Windows llega a la red a través de algo más pequeño — una VPN, PPPoE o cualquier túnel — los paquetes que superan esa MTU de ruta real se descartan en algún punto intermedio.

El descubrimiento de MTU de ruta debería encargarse justo de esto: el salto que no puede reenviar el paquete devuelve un ICMP fragmentation needed y el emisor se echa atrás. Muchas VPN y cortafuegos descartan ese ICMP, así que la respuesta nunca llega. Los paquetes pequeños siguen fluyendo y los grandes desaparecen en silencio: un agujero negro de PMTU. Para SSH, eso parece una conexión que se detuvo sin motivo.

Confírmalo

Desde dentro de WSL, comprueba qué declara la interfaz:

ip link show eth0

Después busca el tamaño que de verdad sobrevive al trayecto. Estos pings activan el bit de no fragmentar, y el tamaño total es la carga útil más 28 bytes de cabecera, así que -s 1472 sondea un paquete de 1500 bytes. Apunta a algo del otro lado del mismo trayecto — el servidor al que te conectas, o cualquier dirección pública:

ping -M do -s 1472 -c 1 example.com   # 1500 — usually times out
ping -M do -s 1372 -c 1 example.com   # 1400 — usually gets through

Un tiempo de espera agotado es el agujero negro. (Si en su lugar aparece un error local inmediato, el tamaño supera la MTU de tu propia interfaz — baja -s y vuelve a probar.) Estrecha el rango hasta encontrar la carga útil más grande que responde; súmale 28 y esa es tu MTU de ruta real.

Los equivalentes del lado de Windows, desde PowerShell:

ping -f -l 1472 example.com
netsh interface ipv4 show subinterfaces

El segundo lista la MTU de todos los adaptadores. Un adaptador de VPN a 1400 junto a vEthernet (WSL) a 1500 es el desajuste que buscas.

Arréglalo en WSL

Ajusta la interfaz al tamaño que has medido. Surte efecto de inmediato y se pierde en el siguiente apagado:

sudo ip link set dev eth0 mtu 1400

Vuelve a conectar y repite lo que antes se atascaba. Si la salida fluye limpia, el diagnóstico queda confirmado.

Para que persista, haz que WSL lo aplique al arrancar. En /etc/wsl.conf, dentro de la distribución:

[boot]
command = ip link set dev eth0 mtu 1400

Después ejecuta wsl --shutdown desde Windows y vuelve a iniciar la distribución. El comando [boot] necesita un WSL razonablemente actual — compruébalo con wsl --version.

Usa el número que haya dado tu prueba con ping en lugar de copiar 1400. Es un valor de reserva seguro que sortea casi cualquier VPN, pero un valor ajustado a tu trayecto desperdicia menos de cada paquete.

O deja que WSL replique el equipo anfitrión

En Windows 11 22H2 y posteriores con WSL 2.0+, la red en modo reflejado entrega a la distribución las propias interfaces del anfitrión, MTU incluidas, así que el desajuste no llega a producirse. En %UserProfile%\.wslconfig:

[wsl2]
networkingMode=mirrored

Aplícalo con wsl --shutdown. Esto cambia bastante más que la MTU — tanto localhost como el alcance de la LAN se comportan de otra manera — así que es preferible el comando de arranque si una sesión que se atasca es tu único problema.

Cuando el salto de MTU baja está del lado del servidor

WSL no siempre es el extremo limitado; ejecutar la misma prueba con ping desde el servidor te dice qué lado está recortado. Si controlas el router intermedio, recortar el MSS de TCP a la MTU de ruta descubierta arregla de una vez todas las conexiones que pasan por él:

iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN \
  -j TCPMSS --clamp-mss-to-pmtu

Mientras sigues atascado

Cambiar el transporte del host a mosh es un apaño, no una solución. Los datagramas de mosh son lo bastante pequeños para colarse bajo una MTU rota, y repinta la pantalla en lugar de reproducir un flujo de bytes, así que una sesión interactiva sobrevive. El panel de archivos y el canal lateral de tmux siguen yendo por SSH, así que las transferencias grandes pueden seguir atascándose.

Si nada de esto encaja con lo que ves, captura un registro (ajustes → diagnósticos → exportar el registro, consulta diagnósticos) y abre una incidencia en GitHub Issues.