WSL es una trampa de productividad en el mejor sentido: obtienes un userland de Linux real, iteración rápida y acceso a aplicaciones de Windows. Luego añades claves SSH—porque claro que lo haces—y de repente has creado un pequeño y portátil almacén de secretos difícil de auditar que vive dentro de una capa tipo VM y que se sincroniza con sitios que no habías planeado.
El modo de fallo rara vez es “un hacker con capucha”. Eres tú, dentro de tres meses, exportando una distro WSL para “hacer copia de seguridad”, copiando dotfiles en OneDrive, o comiteando una clave porque hiciste una copia recursiva como un mapache impaciente. Hagámoslo como en producción: mínimo privilegio, límites explícitos, configuración reproducible y diagnóstico rápido cuando algo falla.
WSL + claves SSH: el modelo mental que previene filtraciones
Piensa en WSL como una máquina Linux con una carpeta compartida muy permisiva montada en ella (normalmente /mnt/c y similares). Tu directorio home en WSL no es Windows, pero tampoco es un ordenador físico separado que puedas olvidar. Es un sistema de archivos dentro de una imagen de distribución, más mucho pegamento de integración.
Las claves SSH son solo archivos. Ese es todo el problema. Si existen como bytes en disco, pueden copiarse, indexarse, hacerles copia de seguridad, analizarlas por malware, sincronizarlas “de forma útil” o comitearse accidentalmente. Así que tu trabajo no es “configurar SSH”. Tu trabajo es controlar qué sistema de archivos contiene las claves, quién puede leerlas, cómo se desbloquean y qué registras durante la resolución de problemas.
Reglas de la carretera (opinadas, porque pediste algo de producción)
- Genera claves dentro del sistema de archivos Linux de WSL (el
/homede tu distro), no en/mnt/c. Mantén la clave privada fuera del alcance de las herramientas de sincronización de Windows por defecto. - Usa frases de contraseña. Si eres alérgico a ellas, usa claves con soporte hardware o un agente con TTL corto—no “sin frase de contraseña”.
- No compartas una única clave en todas partes. Una clave por límite de identidad: personal, corporativa, CI, acceso de emergencia a producción, etc.
- Fija las claves de host y trata
known_hostscomo parte de la seguridad, no como desorden. Tu yo futuro te lo agradecerá la primera vez que el DNS mienta. - Haz explícito el agente. Las sesiones de WSL se reinician con frecuencia; quieres comportamiento predecible, no indicaciones aleatorias y retrocesos silenciosos.
- Audita con comandos, no con intuiciones. “Debería funcionar” es cómo nacen los incidentes.
Hechos interesantes y contexto histórico (corto, útil)
- SSH reemplazó a rsh/rlogin en los años 90 porque las shells remotas en texto plano eran básicamente un regalo para los sniffers de paquetes.
- RSA fue el algoritmo público por defecto durante años, pero los valores por defecto modernos tienden hacia Ed25519 por su velocidad y opciones de parámetros más seguras.
- OpenSSH añadió soporte para llaves FIDO/U2F (como
sk-ssh-ed25519@openssh.com) para reducir el riesgo de exfiltración de claves. ssh-agentexiste porque las frases de contraseña son buenas, pero teclearlas 40 veces al día es la forma en que la gente “soluciona” la seguridad deshabilitándolas.- El archivo
known_hostses la capa anti-phishing de SSH: es cómo SSH detecta cambios man-in-the-middle sin necesitar una PKI global para hosts. - WSL1 y WSL2 difieren mucho en redes: WSL2 ejecuta una VM ligera con NAT, lo que puede afectar el reenvío de agentes y el debugging de “por qué localhost se comporta raro”.
- Los permisos de archivos de Windows no se mapean bien a POSIX en
/mnt/c; ese desajuste es por qué SSH se queja de “permisos demasiado abiertos”. - GitHub dejó de aceptar firmas SHA-1 débiles para algunos flujos; de manera similar, los ecosistemas SSH empujan gradualmente a los usuarios fuera de algoritmos antiguos.
Modelo de amenaza: cómo se filtran las claves en el mundo real
La mayoría de las filtraciones de claves SSH son operacionales, no cinematográficas. Aquí están los sospechosos habituales en entornos WSL:
1) El archivo termina en Windows cuando no te diste cuenta
Quizás copiaste ~/.ssh a un directorio de Windows para “usarlo en VS Code”. Quizás un repositorio de dotfiles tiene un symlink que resuelve en /mnt/c. Quizás editaste archivos bajo /mnt/c porque era cómodo. Los indexadores de búsqueda de Windows, los clientes de sincronización en la nube, DLP corporativo y las herramientas de seguridad del endpoint ahora pueden ver tus secretos.
2) Copias de seguridad y exportaciones
Las exportaciones de distro WSL (wsl --export) producen un tarball del sistema de archivos de la distro. Ese tarball contiene tus claves privadas a menos que las excluyas. Es una “copia de seguridad” conveniente y también una vía de filtración muy portátil.
3) Logs de depuración y pastebins (el desastre silencioso)
La salida de depuración de SSH es mayormente segura, pero tu historial de shell, comandos copiados y scripts de resolución rápida pueden imprimir rutas sensibles, ubicaciones de sockets de agente y, a veces, material de clave si no tienes cuidado. La gente pega todo el ~/.ssh/config en tickets. Entonces el sistema de tickets se convierte en tu gestor de secretos. Brillante.
4) Clave equivocada usada en el lugar equivocado
Es fácil usar accidentalmente tu “clave para todo” contra el host equivocado, especialmente si dependes de identidades cargadas en el agente y no controlas IdentitiesOnly. Así las claves acaban autorizadas en sistemas que nunca debían tocar.
5) Omitir verificación de clave de host “porque es molesto”
Desactivar la comprobación estricta de claves de host para “arreglar CI” o “hacer bootstrap más fácil” es un clásico auto-gol. Puede que no estés filtrando claves privadas, pero sí facilitas enormemente la captura de credenciales y MITM.
Configuración segura: generar, almacenar y usar claves en WSL
Decide dónde vive la clave privada (elige una)
- Mejor por defecto: las claves privadas viven en el sistema de archivos Linux de WSL bajo
/home/<user>/.ssh. Windows solo puede alcanzarlas si deliberadamente las copias hacia fuera. - Mejor para alta garantía: claves con respaldo hardware (FIDO2/YubiKey) para que no exista una clave privada exportable en disco.
- A veces aceptable: claves almacenadas en Windows con un agente nativo de Windows, luego usadas desde WSL mediante un puente. Puede ser válido en entornos corporativos donde Windows está fuertemente gestionado y Linux no. Pero aumenta la complejidad cross-boundary.
Si dudas: mantenlas en WSL primero, añade una frase de contraseña y usa un agente con caché limitado por tiempo. No te compliques en el día uno.
Genera claves (Ed25519 salvo que tengas una razón para no hacerlo)
Las claves Ed25519 son rápidas, compactas y ampliamente soportadas en OpenSSH moderno. Usa una frase de contraseña fuerte. Tu frase no es una contraseña; es un elemento disuasorio si roban el archivo de la clave.
Configura permisos correctos (o SSH se negará a ayudarte)
OpenSSH es estricto con los permisos de clave privada. Eso es bueno. En WSL, también es una trampa común cuando colocas claves en /mnt/c donde los permisos son raros.
Usa configuración por host para dejar de improvisar
La mayoría de los “problemas de SSH” son realmente “demasiado comportamiento implícito”. Pon bloques de host explícitos en ~/.ssh/config y controla IdentityFile, IdentitiesOnly, User y algoritmos de clave. La idea es que el camino correcto sea el más fácil.
Cita (idea parafraseada)
Idea parafraseada: la esperanza no es una estrategia
— atribuida a Gordon R. Dickson; usada a menudo en cultura de ingeniería como recordatorio operacional.
La seguridad de claves SSH en WSL es la misma lección: no esperes que tus claves “no terminen en Windows”. Haz que les sea difícil.
Agente SSH en WSL: deja de escribir frases de contraseña, no inicies un incendio
Un agente es una compensación: conveniencia por una ventana limitada de exposición. Sin agente, la gente elige frases de contraseña débiles o sin frase. Con un agente descuidado, la gente mantiene claves descifradas disponibles para siempre. Elige el punto medio: agente + TTL + identidades explícitas.
Qué quieres de una configuración de agente
- El socket del agente existe y es estable por sesión de inicio.
- Las claves se cargan deliberadamente, no implícitamente desde rutas aleatorias.
- Las claves expiran del agente (con límite temporal) a menos que las vuelvas a añadir intencionalmente.
- SSH elige solo la identidad destinada para cada host.
Un chiste corto, porque hablamos de agentes: Un agente SSH es como dejar la llave de tu casa con un portero. Genial hasta que el portero hace turno doble y nunca se va a casa.
Reenvío de agente: no lo hagas en todas partes
Reenviar tu agente (-A) puede ser útil para saltar a través de bastiones, pero aumenta el riesgo. Si un host remoto puede acceder a tu socket de agente reenviado, puede potencialmente usar tus claves (no copiarlas, pero sí usarlas) mientras el reenvío esté activo. Úsalo solo para hosts en los que confías tanto como confías en tu portátil. Es decir: con precaución.
El límite con Windows: donde la conveniencia devora tus secretos
Sistema de archivos de WSL vs /mnt/c
Dentro de WSL2, el sistema de archivos de tu distro se almacena en un disco virtual. Se comporta como Linux espera. Bajo /mnt/c, estás en un sistema de archivos de Windows con capas de traducción. Esa traducción es excelente para editar archivos; es una responsabilidad para la semántica de permisos de Linux y la higiene de secretos.
Por qué /mnt/c es un mal lugar para claves privadas
- Los permisos de Windows no son permisos POSIX; SSH puede negarse a usar claves por “permisos demasiado abiertos”.
- Los clientes de sincronización en la nube pueden ingerirlas y replicarlas.
- El indexado y antivirus del endpoint pueden escanearlas. No siempre es malicioso, pero amplía la superficie de ataque.
- DLP corporativo puede marcarlas o ponerlas en cuarentena, rompiendo tu flujo de trabajo de la manera más confusa posible.
Cuando el almacenamiento en Windows está justificado
Si tu entorno corporativo exige claves almacenadas en un agente gestionado por Windows (o credenciales con respaldo hardware) y WSL es “mejor esfuerzo”, entonces sí: guarda las claves en Windows y hace que WSL sea un consumidor. Pero trátalo como un proyecto de integración. Documentalo. Pruébalo después de actualizaciones. No lo hagas “a ojo” con symlinks.
Tareas prácticas (comandos + salidas + decisiones)
A continuación hay tareas prácticas que puedes ejecutar hoy. Cada una incluye: el comando, una salida representativa, qué significa la salida y la decisión que tomas a partir de ella.
Task 1: Confirmar que realmente estás en WSL y qué versión importa
cr0x@server:~$ uname -a
Linux devbox 5.15.133.1-microsoft-standard-WSL2 #1 SMP Wed Oct 11 00:00:00 UTC 2023 x86_64 GNU/Linux
Significado: “microsoft-standard-WSL2” te indica que este es un comportamiento de kernel de WSL2 (VM/NAT). Eso afecta supuestos de red e integraciones.
Decisión: Si estás depurando reenvío de agente o “por qué Windows no llega a este socket”, ten en cuenta los límites de WSL2 y planifica en consecuencia.
Task 2: Ver dónde vive tu directorio home (sistema Linux o montaje de Windows)
cr0x@server:~$ df -h ~
Filesystem Size Used Avail Use% Mounted on
/dev/sdc 251G 32G 207G 14% /
Significado: El home está en el sistema de archivos raíz de Linux, no en /mnt/c.
Decisión: Bien. Mantén ~/.ssh aquí.
Task 3: Detectar si ~/.ssh está en Windows (malo) sin adivinar
cr0x@server:~$ readlink -f ~/.ssh
/home/cr0x/.ssh
Significado: La ruta real está bajo /home. Si ves /mnt/c/..., tu directorio SSH está en Windows.
Decisión: Si se resuelve bajo /mnt/c, mueve las claves a WSL y corrige permisos.
Task 4: Listar claves y permisos; detectar filtraciones obvias
cr0x@server:~$ ls -la ~/.ssh
total 28
drwx------ 2 cr0x cr0x 4096 Feb 5 10:12 .
drwxr-xr-x 19 cr0x cr0x 4096 Feb 5 09:40 ..
-rw------- 1 cr0x cr0x 464 Feb 5 10:12 config
-rw------- 1 cr0x cr0x 419 Feb 5 10:11 id_ed25519
-rw-r--r-- 1 cr0x cr0x 99 Feb 5 10:11 id_ed25519.pub
-rw------- 1 cr0x cr0x 1520 Feb 5 10:12 known_hosts
Significado: El directorio es 700, las claves privadas son 600. Eso es lo que SSH espera.
Decisión: Si las claves privadas son legibles por grupo/otros, corrige inmediatamente con chmod (tarea siguiente).
Task 5: Corregir permisos en un solo paso (valores por defecto seguros)
cr0x@server:~$ chmod 700 ~/.ssh
cr0x@server:~$ chmod 600 ~/.ssh/id_ed25519 ~/.ssh/config ~/.ssh/known_hosts
cr0x@server:~$ chmod 644 ~/.ssh/id_ed25519.pub
Significado: Sin salida significa éxito.
Decisión: Si esto falla en /mnt/c, esa es tu señal para dejar de almacenar claves privadas en montajes de Windows.
Task 6: Generar una nueva clave Ed25519 con un KDF fuerte
cr0x@server:~$ ssh-keygen -t ed25519 -a 64 -f ~/.ssh/id_ed25519_work -C "work-wsl"
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/cr0x/.ssh/id_ed25519_work
Your public key has been saved in /home/cr0x/.ssh/id_ed25519_work.pub
The key fingerprint is:
SHA256:8vQZrY4eKJf1YqE6k6G4l3g6i4lqf7RkR5u9M6w8a2k work-wsl
The key's randomart image is:
+--[ED25519 256]--+
| . . . . . |
| . . o . o |
| . + . + |
| o . = |
| . . S |
| o o |
| . = + |
| + = . |
| o.. |
+----[SHA256]-----+
Significado: -a 64 incrementa las rondas KDF para protección de la frase. Esto ralentiza el ataque por fuerza bruta si el archivo es robado.
Decisión: Usa una frase de contraseña. Si no puedes, usa claves con respaldo hardware en lugar de “sin frase”.
Task 7: Verificar que la clave privada está cifrada (no en texto plano)
cr0x@server:~$ head -n 2 ~/.ssh/id_ed25519_work
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
Significado: Aún verás un encabezado incluso cuando está cifrada, pero no puedes confirmar el cifrado solo por la primera línea.
Decisión: Usa ssh-keygen -y para forzar la solicitud de frase (siguiente tarea). Si no pide frase, probablemente creaste una clave sin cifrar.
Task 8: Confirmar comportamiento de solicitud de frase
cr0x@server:~$ ssh-keygen -y -f ~/.ssh/id_ed25519_work >/dev/null
Enter passphrase:
Significado: La solicitud indica que la clave está protegida por frase (o al menos requiere descifrado).
Decisión: Si no hay solicitud y tiene éxito, tu clave probablemente está sin cifrar—considera emitirla de nuevo con frase.
Task 9: Crear una entrada estricta en SSH config para que se use la clave correcta
cr0x@server:~$ cat > ~/.ssh/config <<'EOF'
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
IdentitiesOnly yes
PreferredAuthentications publickey
EOF
cr0x@server:~$ chmod 600 ~/.ssh/config
Significado: IdentitiesOnly yes evita que SSH intente todas las claves del agente y cause bloqueos o flujos de autenticación extraños.
Decisión: Usa hosts con nombre (github-work) para evitar mezclar claves entre identidades.
Task 10: Validar qué usará realmente SSH (sin adivinar)
cr0x@server:~$ ssh -G github-work | egrep '^(hostname|user|identityfile|identitiesonly|preferredauthentications) '
hostname github.com
user git
identityfile ~/.ssh/id_ed25519_work
identitiesonly yes
preferredauthentications publickey
Significado: ssh -G imprime la configuración resuelta después de includes, bloques match, etc.
Decisión: Si ves un identityfile o user inesperado, corrige tu config antes de depurar otra cosa.
Task 11: Iniciar un agente y cargar una clave con TTL
cr0x@server:~$ eval "$(ssh-agent -s)"
Agent pid 1173
cr0x@server:~$ ssh-add -t 1h ~/.ssh/id_ed25519_work
Enter passphrase for /home/cr0x/.ssh/id_ed25519_work:
Identity added: /home/cr0x/.ssh/id_ed25519_work (work-wsl)
Significado: La clave está cacheada en memoria por una hora.
Decisión: Los TTL son un seguro barato. Si necesitas más tiempo, hazlo una elección consciente, no el defecto.
Task 12: Confirmar qué claves están cargadas en el agente
cr0x@server:~$ ssh-add -l
256 SHA256:8vQZrY4eKJf1YqE6k6G4l3g6i4lqf7RkR5u9M6w8a2k work-wsl (ED25519)
Significado: Tu agente tiene actualmente exactamente una identidad cargada.
Decisión: Si ves un montón de claves que habías olvidado, elimínalas: ssh-add -D, y luego añade solo lo que necesitas.
Task 13: Ejecutar una prueba SSH en modo verboso y leerla como un SRE
cr0x@server:~$ ssh -vvv github-work
OpenSSH_9.6p1 Ubuntu-3ubuntu13, OpenSSL 3.0.2 15 Mar 2022
debug1: Reading configuration data /home/cr0x/.ssh/config
debug1: /home/cr0x/.ssh/config line 1: Applying options for github-work
debug1: Connecting to github.com [140.82.112.3] port 22.
debug1: Authentication succeeded (publickey).
Authenticated to github.com ([140.82.112.3]:22).
Significado: Puedes ver exactamente qué config se aplicó, qué host/puerto y si la autenticación con clave pública funcionó.
Decisión: Si intenta la clave equivocada, corrige config (IdentityFile, IdentitiesOnly) y estado del agente; no sigas intentando de forma indefinida.
Task 14: Comprobar fijado de clave de host y cambios inesperados
cr0x@server:~$ ssh-keygen -F github.com -f ~/.ssh/known_hosts | head
# Host github.com found: line 3
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...
Significado: Tienes una entrada de clave de host fijada para ese host.
Decisión: Si una clave de host cambia inesperadamente, trátalo como incidente de seguridad hasta que se demuestre lo contrario. No borres reflexivamente known_hosts.
Task 15: Detectar material de clave accidental bajo /mnt/c (escaneo de filtraciones)
cr0x@server:~$ grep -R --line-number --binary-files=without-match "BEGIN OPENSSH PRIVATE KEY" /mnt/c/Users/cr0x 2>/dev/null | head
/mnt/c/Users/cr0x/Downloads/wsl-export.tar:1:-----BEGIN OPENSSH PRIVATE KEY-----
Significado: Encontraste un encabezado de clave privada dentro de un archivo en el lado de Windows (aquí: un tar de exportación). Esa es una vía real de filtración.
Decisión: Trátala como comprometida hasta verificar contención. Rota claves y limpia el artefacto. También corrige tu flujo de exportación/copia de seguridad.
Task 16: Identificar si tu repositorio Git contiene secretos antes de hacer push
cr0x@server:~$ git status --porcelain
?? .ssh/id_ed25519_work
?? .ssh/id_ed25519_work.pub
Significado: Estás a punto de commitear tus claves SSH. No “quizás.” Lo estás haciendo.
Decisión: Añade .ssh/ a .gitignore, elimina los archivos del área de trabajo y rota si algo fue empujado a algún sitio.
Task 17: Confirmar que la interoperabilidad con Windows no está copiando la config SSH silenciosamente (chequeo de sanidad)
cr0x@server:~$ ls -la /mnt/c/Users/cr0x/.ssh 2>/dev/null
total 12
drwxr-xr-x 1 cr0x cr0x 4096 Feb 5 09:55 .
drwxr-xr-x 1 cr0x cr0x 4096 Feb 5 09:20 ..
-rw-r--r-- 1 cr0x cr0x 412 Feb 5 09:55 config
Significado: Hay una config SSH en el lado de Windows. Algunas herramientas (incluyendo OpenSSH de Windows y herramientas Git) pueden usarla.
Decisión: Decide deliberadamente: manten separados los configs de Windows y WSL, o estandariza en uno y documenta el límite. “Dos configs que divergen” se convierte en fábrica de tickets.
Guion de diagnóstico rápido
Este es el flujo “está roto y tengo cinco minutos”. Prioriza la señal. Puedes profundizar después.
Primero: ¿SSH está usando la configuración que crees?
- Ejecuta
ssh -G <host-alias>y confirmahostname,useryidentityfile. - Si
identityfilees incorrecto, corrige~/.ssh/configantes de tocar agentes, permisos o servidores.
Segundo: ¿La clave es accesible y tiene permisos correctos?
- Comprueba
ls -la ~/.sshy asegura que las claves privadas sean600, y el directorio700. - Si las claves están en
/mnt/c, asume comportamiento raro de permisos y muévelas a WSL.
Tercero: ¿El estado del agente es sano?
- Ejecuta
ssh-add -l. Si da error, tu agente no está en ejecución oSSH_AUTH_SOCKes incorrecto. - Si lista diez claves, depura. Mantén el agente mínimo y explícito.
Cuarto: ¿El servidor te rechaza o no estás ofreciendo lo que quiere?
- Usa
ssh -vvvuna vez, lee las líneas sobreOffering public keyyAuthentication succeeded/failed. - Si el servidor dice “too many authentication failures”, estás ofreciendo demasiadas claves. Bloquea
IdentitiesOnly.
Quinto: Las advertencias de clave de host no son “ruido”
- Si ves advertencias de cambio de clave de host, para. Verifica fuera de banda si el host fue reconstruido o comprometido.
Errores comunes: síntoma → causa raíz → arreglo
1) Síntoma: “Bad permissions” o “Unprotected private key file”
Causa raíz: La clave privada vive en /mnt/c o tiene modo/propiedad demasiado permisiva.
Arreglo: Mueve la clave al sistema de archivos Linux de WSL y establece permisos estrictos.
cr0x@server:~$ mv /mnt/c/Users/cr0x/.ssh/id_ed25519 ~/.ssh/id_ed25519_windows_moved
cr0x@server:~$ chmod 700 ~/.ssh
cr0x@server:~$ chmod 600 ~/.ssh/id_ed25519_windows_moved
2) Síntoma: “Permission denied (publickey)” después de que solía funcionar
Causa raíz: Rotaste claves, cambiaste el contenido del agente, o tu config SSH ahora apunta a un IdentityFile diferente.
Arreglo: Valida con ssh -G, luego asegúrate de que la clave correcta esté cargada.
cr0x@server:~$ ssh -G myhost | egrep '^(identityfile|identitiesonly|user|hostname) '
identityfile ~/.ssh/id_ed25519_work
identitiesonly yes
user deploy
hostname myhost
3) Síntoma: “Too many authentication failures”
Causa raíz: El agente tiene muchas identidades y SSH las ofrece en secuencia hasta que el servidor desconecta.
Arreglo: Usa IdentitiesOnly yes y especifica un único IdentityFile por alias de host. También depura el agente.
cr0x@server:~$ ssh-add -D
All identities removed.
cr0x@server:~$ ssh-add -t 30m ~/.ssh/id_ed25519_work
Enter passphrase for /home/cr0x/.ssh/id_ed25519_work:
Identity added: /home/cr0x/.ssh/id_ed25519_work (work-wsl)
4) Síntoma: Verificación de clave de host fallida tras reconstrucción
Causa raíz: La clave de host cambió (reconstrucción legítima, o no). Tu entrada en known_hosts está obsoleta.
Arreglo: Verifica la nueva huella de clave de host fuera de banda. Luego elimina la entrada antigua por host y vuelve a añadir conectando.
cr0x@server:~$ ssh-keygen -R myhost -f ~/.ssh/known_hosts
# Host myhost found: line 12
/home/cr0x/.ssh/known_hosts updated.
Original contents retained as /home/cr0x/.ssh/known_hosts.old
5) Síntoma: Tu clave aparece en un índice de búsqueda de Windows / sincronización en la nube
Causa raíz: Copiaste ~/.ssh en Windows, o exportaste WSL y guardaste el tarball en una ubicación sincronizada.
Arreglo: Asume exposición. Rota claves, elimina artefactos y ajusta exportación/copia de seguridad para excluir secretos.
6) Síntoma: SSH funciona en terminal WSL pero falla en VS Code / GUI de Git
Causa raíz: La herramienta usa OpenSSH de Windows, no OpenSSH de WSL, por lo tanto lee config y claves diferentes.
Arreglo: Decide qué lado posee SSH para ese flujo. Configura la herramienta explícitamente para usar el binario y almacén de claves correctos. No mantengas dos universos paralelos a menos que disfrutes de la angustia existencial.
7) Síntoma: El agente funciona en una pestaña de shell pero no en otra
Causa raíz: Las variables de entorno del socket del agente no se exportan de forma consistente, o iniciaste una sesión nueva sin fuente del setup del agente.
Arreglo: Usa una estrategia consistente de arranque de agente y guarda SSH_AUTH_SOCK en un lugar predecible por sesión (o confía en el gestor de servicios de tu distro si está disponible).
Tres mini-historias corporativas desde la trinchera
Mini-historia 1: El incidente causado por una suposición errónea
Implementaron WSL como entorno estándar de desarrollo para un equipo que gestionaba infraestructura de producción. Fue una decisión sensata: herramientas consistentes, menos “funciona en mi máquina” y onboarding más fácil. Las claves se generaron en WSL, todos usaban frases de contraseña y la casilla de cumplimiento se marcó con un satisfactorio chasquido.
La suposición errónea fue sutil: “Si está dentro de WSL, no está en Windows”. Eso era mayormente cierto—hasta que un desarrollador exportó su distro para poder migrar a un portátil nuevo. El tarball de exportación aterrizó en una carpeta sincronizada corporativa porque ahí estaban las instrucciones de “Migración de portátil” para colocar archivos grandes.
Nada explotó de inmediato. Ese es el peor tipo de fallo. Una semana después, las herramientas de seguridad marcaron un patrón de firma de clave privada dentro del almacén sincronizado. La clave no fue usada activamente (según lo que pudieron probar), pero la organización tuvo que tratarla como comprometida. Hubo revisiones de acceso. Se rotaron claves. Se limpiaron authorized_keys en bastiones. La gente se enfadó con el “papeleo”.
La solución no fue heroica. Actualizaron el playbook interno: las exportaciones de WSL se tratan como sensibles; las exportaciones deben cifrarse en reposo; y ~/.ssh se excluye de exportaciones salvo que sea imprescindible. También introdujeron claves con respaldo hardware para acceso a producción, así las exportaciones no portarían joyas de la corona.
Mini-historia 2: La optimización que salió mal
Otro equipo quería “sin prompts” en desarrollo. Las frases de contraseña ralentizaban la automatización, decían, y sus operaciones con repositorios eran constantes. Así que estandarizaron claves privadas sin cifrar dentro de WSL, además de una imagen base compartida ampliamente para acelerar nuevas incorporaciones. Se veía genial en demos: clona, compila, despliega, sin interrupciones.
Luego llegó el revés: las imágenes base se copiaron por todas partes. La gente comprimía su distro WSL para “compartir rápido”. La máquina de un contratista se vio comprometida por malware de consumo que ni siquiera buscaba específicamente SSH—simplemente raspaba archivos que parecían claves. De repente, las claves sin cifrar eran exactamente lo que el atacante necesitaba. Sin fuerza bruta. Sin sofisticación. Solo “encuentra archivo, usa archivo”.
Pasaron semanas desenredando qué clave tenía acceso a qué. Lo peor no fue la contención inmediata. Fue la arqueología: claves antiguas, hosts olvidados, entradas stale en authorized_keys en servidores de larga vida. La “optimización” había convertido deuda operativa en un multiplicador de incidentes de seguridad.
Después, adoptaron frases de contraseña + TTL en el agente y estandarizaron claves por servicio con acceso estrecho. La productividad se mantuvo alta; los prompts fueron manejables; y la superficie de riesgo se redujo drásticamente. Resulta que puedes tener rápido y seguro. Solo no puedes tener “rápido porque ignoramos el problema”.
Mini-historia 3: La práctica aburrida pero correcta que salvó el día
Un equipo de plataforma tenía una costumbre que parecía quisquillosa: cada ingeniero mantenía un estricto ~/.ssh/config con alias de host nombrados, archivos de identidad explícitos y IdentitiesOnly yes. También fijaban claves de host y se negaban a desactivar la comprobación estricta de claves de host salvo en flujos de bootstrap muy controlados.
Durante una ventana de respuesta a incidentes, tuvieron que acceder a una flota a través de un bastion. El DNS estaba parcialmente roto y algunos ingenieros eran dirigidos a IPs incorrectas. Aquí muchos equipos se vuelven laxos: “conéctate ya, lo arreglamos después”.
Pero SSH rechazó un subconjunto de conexiones debido a discrepancias de claves de host. ¿Molesto? En el momento, sí. ¿Valioso? Absolutamente. Les impidió introducir credenciales y ejecutar comandos en máquinas equivocadas mientras el estrés era alto y la atención baja.
El equipo verificó las claves de host correctas a través de su canal de inventario confiable, actualizó registros donde hacía falta y solo entonces reconectó. Ese comportamiento aburrido y disciplinado les ahorró de empeorar el incidente. La fiabilidad suele ser el arte de negarse a hacer lo fácil y equivocado.
Listas de verificación / plan paso a paso
Lista A: Máquina WSL nueva, SSH seguro en 20 minutos
- Crea
~/.sshen el sistema de archivos Linux de WSL y bloquea permisos. - Genera una clave Ed25519 con frase de contraseña y rondas KDF decentes.
- Crea
~/.ssh/configcon alias de host explícitos yIdentitiesOnly yes. - Inicia un agente y carga la clave con TTL (
ssh-add -t). - Conéctate una vez con
ssh -vvvpara confirmar selección de clave y fijado de host. - Escanea montajes de Windows en busca de copias accidentales de claves privadas.
Lista B: Prevenir filtraciones vía copias de seguridad y exportaciones
- Decide si las exportaciones de WSL pueden contener secretos.
- Si debes exportar, cifra el tarball inmediatamente y guárdalo solo en ubicaciones aprobadas.
- Prefiere claves con respaldo hardware para producción para que las exportaciones no lleven las joyas de la corona.
- Realiza un grep periódico en rutas de Windows en busca de encabezados de clave privada.
Lista C: Rotación de claves sin drama
- Genera una nueva clave con un nombre de archivo nuevo (no sobrescribas de inmediato).
- Añade la nueva clave pública al servicio remoto o a
authorized_keys. - Actualiza
~/.ssh/configpara apuntar a la nueva clave para un alias de host. - Prueba con
ssh -vvvy verifica que se ofrezca la clave correcta. - Elimina la clave antigua del remoto y después borra la clave privada antigua localmente.
- Vacía identidades del agente y vuelve a cargar solo la nueva clave.
Segundo chiste corto, porque mereces un descanso: Rotar claves se siente como usar hilo dental—nadie lo disfruta, pero la alternativa es mucho más cara.
Preguntas frecuentes
1) ¿Debo generar claves SSH en Windows o en WSL?
Si trabajas principalmente en WSL, genera y almacena claves en el sistema de archivos Linux de WSL (/home). Manténlas en Windows solo si tienes una estrategia deliberada de agente gestionado por Windows.
2) ¿Es seguro poner mi clave privada bajo /mnt/c?
No es una buena opción por defecto. Heredas indexado y comportamientos de sincronización de Windows y mapeo de permisos desordenado. Pon las claves privadas en el sistema de archivos nativo de WSL.
3) ¿Cuál es el mejor tipo de clave en 2026?
Para uso general: Ed25519. Para alta garantía: claves con respaldo hardware (FIDO2) donde la clave privada no es exportable. Usa RSA solo si debes soportar sistemas legacy.
4) ¿Realmente necesito una frase de contraseña si uso ssh-agent?
Sí. El agente te evita reescribirla. La frase protege si el archivo de la clave es copiado. Resuelven problemas distintos.
5) ¿Por qué SSH dice que los permisos de mi clave son demasiado abiertos?
OpenSSH se niega a usar claves privadas legibles por otros. En montajes de Windows, los permisos a menudo parecen demasiado permisivos. Mueve la clave al sistema de archivos de WSL y aplica chmod 600.
6) ¿Por qué funciona en terminal pero no en mi cliente Git?
Tu cliente Git puede estar usando OpenSSH de Windows y el almacén/config de Windows, no los de WSL. Decide cuál quieres y configura la herramienta en consecuencia.
7) ¿Es seguro el reenvío de agente?
Seguro-ish cuando se usa con moderación en hosts de confianza; arriesgado cuando se usa ampliamente. El reenvío permite que hosts remotos usen tu agente mientras estás conectado. No reenvíes a entornos en los que no confíes completamente.
8) ¿Cómo sé qué clave está ofreciendo SSH?
Usa ssh -vvv y busca líneas como “Offering public key” y la ruta del archivo de identidad. También usa ssh -G para ver la config resuelta.
9) ¿Qué hago si accidentalmente commité una clave privada?
Asume que está comprometida. Rota inmediatamente, elimínala de ubicaciones autorizadas y purga el historial donde sea posible. Luego audita copias (logs de CI, forks, mirrors).
10) ¿Puedo compartir una clave para todos los hosts para simplificar?
Puedes, pero no deberías. Una clave en todas partes convierte una sola filtración en una compromisión total. Usa múltiples claves por identidad y alcance.
Conclusión: próximos pasos que puedes hacer hoy
Las claves SSH en WSL no son inherentemente riesgosas. Lo arriesgado es tratar a WSL como un límite mágico de seguridad y tratar los archivos de clave como configuración inofensiva. Son credenciales. Trátalas como tal.
- Mueve claves privadas fuera de
/mnt/cy hacia tu directorio home de WSL. - Asegúrate de que cada clave privada esté protegida por frase y con permisos (
700para~/.ssh,600para claves privadas). - Usa alias de host en
~/.ssh/configconIdentitiesOnly yespara que siempre se use la clave correcta. - Ejecuta un agente con TTLs y mantén las identidades cargadas al mínimo.
- Escanea carpetas del lado de Windows en busca de copias accidentales de claves, especialmente tarballs de exportación y “Downloads”.
Haz esos cinco y evitarás las vías de filtración más comunes. Además depurarás más rápido, porque tu comportamiento SSH será determinista en lugar de una casa encantada de valores por defecto.