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_keysvs.administrators_authorized_keys), permisos NTFS (el archivo para admins requiere ACLs estrictas) y configuraciones desshd_configantes de deshabilitar WinRM.
- Nuevos vectores de ataque: El uso de SSH nativo en Windows introduce riesgos si no se configuran adecuadamente:
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
| Componente | Versión base | Disponibilidad | Notas |
|---|---|---|---|
| OpenSSH client | 8.1p1 (Windows) | Windows 10 1809+/Server 2019+ | Incluye BLOCK33 , BLOCK34 , BLOCK35 , BLOCK36 , BLOCK37 . |
| OpenSSH server | 9.5p1 (Server 2025) | Preinstalado (deshabilitado) | Versión más reciente que en Windows 10/11 (trail de upstream). |
| Win32-OpenSSH (MSI) | 10.0-preview | Opcional en todas las versiones | Incluye algoritmos post-cuánticos ( BLOCK38 ). |
| PowerShell 7 | 7.6 (LTS) | Descarga independiente | Requiere registro manual como subsistema SSH en BLOCK39 . |
- En Windows 10/11 y Server 2019/2022,
sshdno está preinstalado. Se activa instalando la Capacidad OpcionalOpenSSH.Servermediante:
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,
sshdya 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:
- Usuarios estándar:
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)"
- 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:
- Registrar PowerShell 7 como subsistema SSH:
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
- Reiniciar el servicio:
Restart-Service sshd
Limitaciones vs. WinRM:- No soporta session configurations ni JEA.
- No carga
$PROFILEen 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: usarEnter-PSSessiondesde 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 sshdPara 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 sshd2. 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 permisosPara 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-windowsDesde 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_ed255194. Monitorear y ajustar políticas
- Habilitar
ssh-agenten 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:
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:
- 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.
- Configuración de subsistemas: El uso de
progra~1o la creación de symlinks es temporal; la solución definitiva requiere actualizar Win32-OpenSSH a versiones recientes. - 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
