Introducción

En 2006, conectar PowerShell a SSH requería un workaround con Cygwin: un shell sin prompt, ejecutables de terceros y configuraciones opacas como el flag ntsec. El artículo original de Matt Michie terminaba con un ruego desesperado: «por favor, usen SSH». Doce años después, Microsoft lo hizo: incorporó OpenSSH nativamente en Windows, lo incluyó por defecto en Windows Server 2025 y hoy PowerShell 7 remota sobre SSH sin capas intermedias. Pero la promesa inicial tiene matices técnicos que siguen generando incidentes en equipos de infraestructura. Desde rutas de claves divididas por roles de administrador hasta la falta de AuthorizedKeysCommand, hay detalles que convierten una solución elegante en una trampa si no se configuran correctamente.

Qué ocurrió

Microsoft integró OpenSSH en Windows a partir de Windows 10 (1809) y Windows Server 2019, pero el salto definitivo llegó con Windows Server 2025: el servicio sshd ahora viene preinstalado y deshabilitado. En versiones anteriores (10, 11, Server 2019/2022), el servidor es una Capacidad Opcional que se instala manualmente. Lo clave es que, en Server 2025, el firewall ya incluye la regla para el puerto 22 al instalar la capacidad, mientras que en versiones anteriores hay que crearla explícitamente si se activa el servidor después de instalar la capacidad.

En paralelo, PowerShell 7.6 (LTS actual) soporta remoting nativo sobre SSH mediante los cmdlets Enter-PSSession, New-PSSession e Invoke-Command, con soporte multiplataforma (Windows, Linux, macOS). Esto reemplaza al antiguo workaround de Cygwin y elimina la dependencia de WinRM para muchos casos de uso. Sin embargo, la integración no es perfecta: algunas funcionalidades avanzadas de WinRM (como Just Enough Administration o session configurations) no están disponibles en el remoting por SSH, lo que obliga a mantener ambos protocolos en entornos híbridos.

Impacto para DevOps / Infraestructura / Cloud / Seguridad

Para equipos de infraestructura:
  • Reducción de complejidad: Eliminar la necesidad de WinRM o PuTTY simplifica la gestión de sesiones remotas, especialmente en entornos híbridos (Windows/Linux). La consola de PowerShell 7 sobre SSH permite piping de objetos entre sistemas, algo imposible con SSH tradicional.
  • Seguridad mejorada: El soporte nativo de OpenSSH en Windows Server 2025 incluye reglas de firewall preconfiguradas y la posibilidad de usar claves post-cuánticas (como mlkem768x25519-sha256) en builds preview de Win32-OpenSSH.
  • Desafíos de migración: Los equipos deben auditar rutas de claves (authorized_keys vs. administrators_authorized_keys), permisos NTFS (el archivo para admins requiere ACLs estrictas) y configuraciones de sshd_config antes de deshabilitar WinRM.
Para equipos de seguridad:
  • Nuevos vectores de ataque: El uso de SSH nativo en Windows introduce riesgos si no se configuran adecuadamente:
Permisos incorrectos en authorized_keys: Si un usuario administrador usa C:\Users\usuario\.ssh\authorized_keys, el servidor ignora el archivo y falla silenciosamente, cayendo en autenticación por contraseña (que podría ser débil).

Falta de AuthorizedKeysCommand: En Linux, es común recuperar claves desde AD o LDAP; en Windows, esto no está soportado, limitando la administración centralizada de claves.

Post-quantum aún en preview: Las builds más nuevas incluyen algoritmos post-cuánticos, pero no están en producción aún (versión actual de Win32-OpenSSH: 10.0-preview).

Para equipos de Cloud:
  • Escalabilidad: La integración nativa permite aprovisionar instancias Windows Server 2025 con SSH habilitado desde el inicio, reduciendo el tiempo de configuración en IaaS (ej: Azure, AWS). Sin embargo, en entornos legacy (Server 2019/2022), la instalación manual sigue siendo necesaria.
  • Multi-cloud: La compatibilidad con SSH nativo en PowerShell 7 facilita la gestión remota en entornos multi-cloud donde Linux es predominante, pero requiere mantener WinRM para escenarios con restricciones de sesión (JEA, constrained endpoints).

Detalles técnicos

OpenSSH en Windows: versiones y componentes

ComponenteVersión baseDisponibilidadNotas
OpenSSH client8.1p1 (Windows)Windows 10 1809+/Server 2019+Incluye BLOCK33, BLOCK34, BLOCK35, BLOCK36, BLOCK37.
OpenSSH server9.5p1 (Server 2025)Preinstalado (deshabilitado)Versión más reciente que en Windows 10/11 (trail de upstream).
Win32-OpenSSH (MSI)10.0-previewOpcional en todas las versionesIncluye algoritmos post-cuánticos (BLOCK38).
PowerShell 77.6 (LTS)Descarga independienteRequiere registro manual como subsistema SSH en BLOCK39.
Diferencias clave entre versiones:
  • En Windows 10/11 y Server 2019/2022, sshd no está preinstalado. Se activa instalando la Capacidad Opcional OpenSSH.Server mediante:
  Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
  

Luego, se inicia el servicio:

  Start-Service sshd
  Set-Service -Name sshd -StartupType Automatic
  
  • En Server 2025, sshd ya está presente pero detenido. Basta con configurarlo y iniciarlo:
  # Instalar firewall rule si no existe (en Server 2025 ya viene creada)
  New-NetFirewallRule -DisplayName "OpenSSH Server (sshd)" -Direction Inbound -Protocol TCP -LocalPort 22 -Action Allow
  Start-Service sshd
  

Configuración de claves: el «gotcha» que persiste

El comportamiento de sshd en Windows depende del rol del usuario:

  1. Usuarios estándar:
– Las claves públicas se guardan en C:\Users\<usuario>\.ssh\authorized_keys.

– Ejemplo de despliegue manual:

     New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.ssh"
     Set-Content -Path "$env:USERPROFILE\.ssh\authorized_keys" -Value (Get-Content ~/.ssh/id_ed25519.pub)
     icacls "$env:USERPROFILE\.ssh\authorized_keys" /inheritance:r /grant:r "$env:USERNAME:(F)"
     
  1. Usuarios administradores:
sshd ignora authorized_keys y usa C:\ProgramData\ssh\administrators_authorized_keys.

Problema común: Si el archivo tiene ACLs incorrectas (ej: permisos para Users), la autenticación falla silenciosamente. La solución es:

     New-Item -Path "C:\ProgramData\ssh\administrators_authorized_keys" -ItemType File -Force
     Set-Content -Path "C:\ProgramData\ssh\administrators_authorized_keys" -Value (Get-Content ~/.ssh/id_ed25519.pub)
     icacls "C:\ProgramData\ssh\administrators_authorized_keys" /inheritance:r /grant:r "NT AUTHORITY\SYSTEM:(F)" /grant:r "BUILTIN\Administrators:(F)"
     
Error típico:

Si un usuario administrador puede conectarse con clave desde una máquina pero no desde otra, la causa casi siempre es la ruta de authorized_keys o los permisos NTFS. No hay mensaje de error explícito; simplemente se cae a autenticación por contraseña.

PowerShell 7 Remoting sobre SSH

Para habilitar el remoting nativo:

  1. Registrar PowerShell 7 como subsistema SSH:
– Opción A (usando progra~1 por bug en Win32-OpenSSH):
     # En C:\ProgramData\ssh\sshd_config
     Subsystem powershell c:/progra~1/powershell/7/pwsh.exe -sshs -NoLogo -NoProfile
     

– Opción B (recomendada, usando symlink):

     New-Item -ItemType SymbolicLink -Path "C:\ProgramData\ssh\pwsh.exe" -Target "$env:ProgramFiles\PowerShell\7\pwsh.exe"
     

Luego en sshd_config:

     Subsystem powershell c:/ProgramData/ssh/pwsh.exe -sshs -NoLogo -NoProfile
     
  1. Reiniciar el servicio:
   Restart-Service sshd
   
Limitaciones vs. WinRM:
  • No soporta session configurations ni JEA.
  • No carga $PROFILE en sesiones remotas.
  • Segundo salto (second-hop): Las sesiones por clave no tienen credenciales de usuario, por lo que no pueden autenticarse en recursos compartidos (ej: \\server\share). Solución temporal: usar Enter-PSSession desde dentro de una sesión ya autenticada.

Qué deberían hacer los administradores y equipos técnicos

1. Auditar y migrar entornos existentes

Para equipos en Windows 10/11 o Server 2019/2022:
# 1. Instalar el servidor SSH (si no está)
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

# 2. Configurar firewall (si no existe la regla)
if (-not (Get-NetFirewallRule -DisplayName "OpenSSH Server (sshd)" -ErrorAction SilentlyContinue)) {
    New-NetFirewallRule -DisplayName "OpenSSH Server (sshd)" -Direction Inbound -Protocol TCP -LocalPort 22 -Action Allow
}

# 3. Habilitar PowerShell 7 como subsistema (usar opción B con symlink)
New-Item -ItemType SymbolicLink -Path "C:\ProgramData\ssh\pwsh.exe" -Target "$env:ProgramFiles\PowerShell\7\pwsh.exe"
Set-Content -Path "C:\ProgramData\ssh\sshd_config" -Value @"
Subsystem powershell c:/ProgramData/ssh/pwsh.exe -sshs -NoLogo -NoProfile
"@
Restart-Service sshd
Para equipos en Server 2025:
# Solo ajustar firewall si la regla no existe (en Server 2025 suele venir creada)
if (-not (Get-NetFirewallRule -DisplayName "OpenSSH Server (sshd)" -ErrorAction SilentlyContinue)) {
    New-NetFirewallRule -DisplayName "OpenSSH Server (sshd)" -Direction Inbound -Protocol TCP -LocalPort 22 -Action Allow
}
Start-Service sshd

2. Migrar claves y validar permisos

Para usuarios estándar:
# Crear .ssh y establecer permisos estrictos
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.ssh"
Set-Content -Path "$env:USERPROFILE\.ssh\authorized_keys" -Value (Get-Content ~/.ssh/id_ed25519.pub)
icacls "$env:USERPROFILE\.ssh\authorized_keys" /inheritance:r /grant:r "$env:USERNAME:(F)"

# Validar que sshd pueda leer el archivo
icacls "$env:USERPROFILE\.ssh\authorized_keys" | Select-String "Everyone|Users"
# Si aparece, ajustar permisos
Para administradores:
# Crear archivo y establecer ACLs estrictas
New-Item -Path "C:\ProgramData\ssh\administrators_authorized_keys" -ItemType File -Force
Set-Content -Path "C:\ProgramData\ssh\administrators_authorized_keys" -Value (Get-Content ~/.ssh/id_ed25519.pub)
icacls "C:\ProgramData\ssh\administrators_authorized_keys" /inheritance:r /grant:r "NT AUTHORITY\SYSTEM:(F)" /grant:r "BUILTIN\Administrators:(F)"

# Verificar que no haya permisos excesivos
icacls "C:\ProgramData\ssh\administrators_authorized_keys" | Select-String "Users|Authenticated Users"

3. Validar la conexión y probar remoting

Desde un cliente Linux/macOS:
ssh -i ~/.ssh/id_ed25519 usuario@servidor-windows
Desde PowerShell 7:
# Conectar por SSH y obtener objetos
$session = New-PSSession -ComputerName servidor-windows -UserName usuario -KeyFilePath ~/.ssh/id_ed25519
Invoke-Command -Session $session -ScriptBlock { Get-Process | Select-Object Name, CPU }
Probar remoting nativo:
# Desde una máquina Linux/macOS a Windows
Enter-PSSession -HostName servidor-windows -UserName usuario -KeyFilePath ~/.ssh/id_ed25519

4. Monitorear y ajustar políticas

  • Habilitar ssh-agent en Windows:
  Set-Service ssh-agent -StartupType Automatic
  Start-Service ssh-agent
  

Luego agregar la clave:

  ssh-add ~/.ssh/id_ed25519
  
  • Deshabilitar contraseñas si es posible:
Editar sshd_config para forzar clave-only:
  PasswordAuthentication no
  PubkeyAuthentication yes
  
  • Auditar logs de SSH:
  Get-WinEvent -LogName "OpenSSH/Operational" | Where-Object { $_.LevelDisplayName -eq "Error" } | Select-Object -First 10
  

Conclusión

La integración nativa de OpenSSH en Windows es el final feliz de una batalla de veinte años, pero el «final feliz» tiene letra chica. Los equipos de infraestructura deben prestar atención a tres puntos críticos:

  1. Rutas de claves y permisos: El comportamiento diferenciado entre usuarios estándar y administradores, junto con los permisos NTFS, sigue siendo la causa número uno de fallos silenciosos.
  2. Configuración de subsistemas: El uso de progra~1 o la creación de symlinks es temporal; la solución definitiva requiere actualizar Win32-OpenSSH a versiones recientes.
  3. Limitaciones del remoting: Aunque PowerShell 7 sobre SSH es multiplataforma y elegante, no reemplaza a WinRM en escenarios con restricciones de sesión o segundo salto.

Si tu equipo aún depende de Cygwin o PuTTY para gestionar PowerShell de forma remota, 2026 es el año para migrar. Pero hazlo con un plan: audita permisos, valida claves y prueba el remoting nativo antes de deshabilitar WinRM por completo. El futuro es SSH, pero el camino tiene trampas que ya conocemos.

FIN

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *