PowerShell Remoting es una de las funcionalidades más potentes del conjunto de herramientas de administración de Windows. Te permite ejecutar comandos, correr scripts y gestionar configuraciones en máquinas remotas — una a la vez o en cientos simultáneamente. En su núcleo, PowerShell Remoting se apoya en Windows Remote Management (WinRM), la implementación de Microsoft del protocolo WS-Management. En esta guía, aprenderás cómo habilitar y configurar WinRM, usar los cmdlets principales de remoting, gestionar credenciales de forma segura, manejar escenarios entre dominios y aprovechar el remoting basado en SSH para la administración multiplataforma.

Requisitos Previos

Antes de comenzar a configurar PowerShell Remoting, asegúrate de tener lo siguiente:

  • Windows Server 2016 o posterior (o Windows 10/11 Pro/Enterprise para máquinas cliente)
  • PowerShell 5.1 o posterior instalado (se recomienda PowerShell 7+ para remoting basado en SSH)
  • Privilegios administrativos tanto en la máquina cliente como en las remotas
  • Conectividad de red en el puerto 5985 (HTTP) o 5986 (HTTPS) entre cliente y servidor
  • Dominio de Active Directory (recomendado pero no requerido — las configuraciones de grupo de trabajo se cubren más adelante)
  • Familiaridad básica con cmdlets de PowerShell y configuración del firewall de Windows

Habilitación y Configuración de WinRM

WinRM está instalado por defecto en los sistemas Windows modernos, pero el servicio típicamente no está en ejecución y las reglas de firewall no están habilitadas en los sistemas operativos cliente. En las ediciones de Windows Server a partir de 2012, WinRM está habilitado por defecto, pero aun así debes verificar la configuración.

Habilitar PSRemoting

La forma más rápida de habilitar todo a la vez es el cmdlet Enable-PSRemoting:

# Ejecutar en una sesión elevada de PowerShell en la máquina remota
Enable-PSRemoting -Force

Este único comando realiza varias acciones: inicia el servicio WinRM, lo configura para inicio automático, crea un listener HTTP en el puerto 5985, añade excepciones al Firewall de Windows y registra las configuraciones de sesión predeterminadas de PowerShell.

Verificar que WinRM Está Escuchando

Después de habilitar, confirma que el servicio está ejecutándose y los listeners están activos:

# Verificar estado del servicio
Get-Service WinRM

# Listar listeners activos
Get-WSManInstance -ResourceURI winrm/config/listener -Enumerate

# Prueba rápida de conectividad desde el cliente
Test-WSMan -ComputerName SERVIDOR01

Configurar TrustedHosts

En un entorno de dominio, Kerberos gestiona la autenticación de forma transparente. En escenarios de grupo de trabajo o entre dominios, necesitas configurar TrustedHosts en la máquina cliente:

# Agregar un solo host
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "SERVIDOR01"

# Agregar múltiples hosts (separados por comas)
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "SERVIDOR01,SERVIDOR02,192.168.1.50"

# Confiar en todos los hosts (NO recomendado para producción)
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*"

# Ver los TrustedHosts actuales
Get-Item WSMan:\localhost\Client\TrustedHosts

Configurar Transporte HTTPS

Para entornos de producción, especialmente a través de redes no confiables, el transporte HTTPS cifra toda la sesión WinRM:

# En el servidor remoto: crear un certificado autofirmado
$cert = New-SelfSignedCertificate -DnsName "SERVIDOR01.contoso.com" `
    -CertStoreLocation Cert:\LocalMachine\My -NotAfter (Get-Date).AddYears(5)

# Crear un listener HTTPS usando la huella digital del certificado
New-WSManInstance -ResourceURI winrm/config/listener `
    -SelectorSet @{Address="*"; Transport="HTTPS"} `
    -ValueSet @{CertificateThumbprint=$cert.Thumbprint}

# Agregar regla de firewall para HTTPS
New-NetFirewallRule -DisplayName "WinRM HTTPS" -Direction Inbound `
    -LocalPort 5986 -Protocol TCP -Action Allow

Configurar mediante Directiva de Grupo

Para un despliegue a nivel de dominio, utiliza la Directiva de Grupo para habilitar WinRM a gran escala:

  1. Navega a Configuración del equipo → Plantillas administrativas → Componentes de Windows → Administración remota de Windows → Servicio WinRM
  2. Habilita Permitir la administración remota del servidor a través de WinRM
  3. Establece el filtro IPv4/IPv6 a * o subredes específicas
  4. Configura Shell remoto de Windows → Permitir el acceso a Shell remoto como Habilitado

Uso de Invoke-Command y Enter-PSSession

PowerShell proporciona dos cmdlets principales para la ejecución remota, cada uno adaptado a diferentes flujos de trabajo.

Invoke-Command — Ejecución por Lotes en Paralelo

Invoke-Command envía un bloque de script a uno o más equipos y los ejecuta en paralelo por defecto (hasta 32 conexiones simultáneas):

# Ejecutar un comando en un solo host remoto
Invoke-Command -ComputerName SERVIDOR01 -ScriptBlock {
    Get-Process | Sort-Object CPU -Descending | Select-Object -First 10
}

# Ejecutar contra múltiples servidores simultáneamente
$servidores = @("SERVIDOR01", "SERVIDOR02", "SERVIDOR03", "SERVIDOR04")
Invoke-Command -ComputerName $servidores -ScriptBlock {
    Get-Service -Name "W3SVC" | Select-Object Status, MachineName
}

# Limitar la concurrencia para entornos grandes
Invoke-Command -ComputerName $servidores -ScriptBlock {
    Restart-Service -Name "Spooler" -Force
} -ThrottleLimit 10

# Ejecutar un archivo de script local en máquinas remotas
Invoke-Command -ComputerName $servidores -FilePath "C:\Scripts\Audit-Security.ps1"

Enter-PSSession — Remoting Interactivo

Enter-PSSession es ideal para resolución de problemas ad-hoc donde necesitas un shell interactivo:

# Iniciar una sesión interactiva
Enter-PSSession -ComputerName SERVIDOR01 -Credential (Get-Credential)

# Ahora estás en SERVIDOR01 — ejecuta comandos como si fuera local
[SERVIDOR01]: PS C:\> Get-EventLog -LogName System -Newest 20
[SERVIDOR01]: PS C:\> Get-Disk | Format-Table
[SERVIDOR01]: PS C:\> Exit-PSSession

Sesiones Persistentes (PSSessions)

Para conexiones repetidas, crea una sesión persistente para evitar la sobrecarga de establecer una nueva conexión cada vez:

# Crear sesiones persistentes
$sesiones = New-PSSession -ComputerName SERVIDOR01, SERVIDOR02, SERVIDOR03

# Reutilizar la sesión en múltiples comandos
Invoke-Command -Session $sesiones -ScriptBlock { Get-HotFix | Select-Object -Last 5 }
Invoke-Command -Session $sesiones -ScriptBlock { Get-WindowsFeature | Where-Object Installed }

# Copiar archivos a través de una sesión
Copy-Item -Path "C:\Deploy\app.zip" -Destination "C:\Install\" -ToSession $sesiones[0]

# Limpiar cuando termines
Remove-PSSession $sesiones

Gestión de Credenciales y Seguridad

El manejo adecuado de credenciales es crucial para el remoting seguro a gran escala.

Uso de Get-Credential y PSCredential

# Solicitud interactiva
$cred = Get-Credential -UserName "CONTOSO\admin" -Message "Ingresa la contraseña de administrador remoto"

# Credencial programática (para automatización — protege la fuente de la contraseña)
$securePass = ConvertTo-SecureString "P@ssw0rd!" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential("CONTOSO\admin", $securePass)

Almacenamiento Seguro de Credenciales

Nunca escribas contraseñas directamente en los scripts. Utiliza uno de estos enfoques:

# Exportar credencial cifrada a archivo (específica de usuario+máquina)
Get-Credential | Export-Clixml -Path "$HOME\cred.xml"

# Importar en otra sesión (mismo usuario, misma máquina únicamente)
$cred = Import-Clixml -Path "$HOME\cred.xml"

# Usar el Administrador de Credenciales de Windows mediante el módulo CredentialManager
Install-Module -Name CredentialManager -Force
New-StoredCredential -Target "WinRM-Admin" -UserName "CONTOSO\admin" `
    -Password "P@ssw0rd!" -Persist LocalMachine
$cred = Get-StoredCredential -Target "WinRM-Admin"

CredSSP para Escenarios de Doble Salto

Cuando un comando remoto necesita acceder a un segundo recurso (el problema del “doble salto”), configura la delegación CredSSP:

# En el cliente: habilitar el rol de cliente CredSSP
Enable-WSManCredSSP -Role Client -DelegateComputer "SERVIDOR01.contoso.com"

# En el servidor: habilitar el rol de servidor CredSSP
Enable-WSManCredSSP -Role Server

# Conectar usando autenticación CredSSP
Invoke-Command -ComputerName SERVIDOR01 -Credential $cred `
    -Authentication CredSSP -ScriptBlock {
    # Ahora puede acceder a recursos de red como carpetas compartidas
    Get-ChildItem "\\FILESERVER\Share$"
}

Advertencia: CredSSP envía las credenciales al servidor remoto. Úsalo solo con máquinas de confianza y preferiblemente a través de HTTPS.

Just Enough Administration (JEA)

Para remoting con privilegios mínimos, configura endpoints JEA que restrinjan lo que los usuarios pueden hacer:

# Crear un archivo de capacidad de rol
New-PSRoleCapabilityFile -Path "C:\JEA\HelpDeskRole.psrc" `
    -VisibleCmdlets @("Restart-Service", "Get-Service", "Get-Process") `
    -VisibleFunctions @("Get-HotFix")

# Crear configuración de sesión
New-PSSessionConfigurationFile -Path "C:\JEA\HelpDesk.pssc" `
    -SessionType RestrictedRemoteServer `
    -RunAsVirtualAccount `
    -RoleDefinitions @{ "CONTOSO\HelpDesk" = @{ RoleCapabilities = "HelpDeskRole" } }

# Registrar el endpoint
Register-PSSessionConfiguration -Name "HelpDesk" -Path "C:\JEA\HelpDesk.pssc"

Remoting Basado en SSH para Multiplataforma

A partir de PowerShell 7, puedes usar SSH como capa de transporte en lugar de WinRM. Esto es especialmente útil para administrar máquinas Linux y macOS junto con servidores Windows.

Instalar y Configurar OpenSSH

# En Windows: instalar el servidor OpenSSH
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Start-Service sshd
Set-Service sshd -StartupType Automatic

# Configurar el subsistema SSH para PowerShell en sshd_config
# Agrega esta línea a C:\ProgramData\ssh\sshd_config:
# Subsystem powershell c:/progra~1/powershell/7/pwsh.exe -sshs -NoLogo -NoProfile
Restart-Service sshd

En Linux, agrega el subsistema de PowerShell a /etc/ssh/sshd_config:

# Instalar PowerShell en Ubuntu
sudo apt-get update && sudo apt-get install -y powershell

# Agregar subsistema a sshd_config
echo "Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile" | sudo tee -a /etc/ssh/sshd_config
sudo systemctl restart sshd

Uso del Remoting Basado en SSH

# Sesión interactiva sobre SSH
Enter-PSSession -HostName servidor-linux01 -UserName admin -SSHTransport

# Ejecutar comandos en Linux desde Windows
Invoke-Command -HostName servidor-linux01 -UserName admin -ScriptBlock {
    uname -a
    df -h
    systemctl status nginx
}

# Apuntar a sistemas operativos mixtos
$sesionWindows = New-PSSession -ComputerName WIN-SRV01 -Credential $cred
$sesionLinux = New-PSSession -HostName LINUX-SRV01 -UserName admin -SSHTransport

Invoke-Command -Session $sesionWindows, $sesionLinux -ScriptBlock {
    if ($IsLinux) { cat /etc/os-release } else { Get-ComputerInfo | Select-Object OsName }
}

Comparativa: WinRM vs Remoting Basado en SSH vs OpenSSH en Windows

CaracterísticaWinRM (HTTP/HTTPS)Remoting Basado en SSH (PS7)OpenSSH en Windows
ProtocoloWS-ManagementSSHSSH
Puertos predeterminados5985 / 59862222
AutenticaciónKerberos, NTLM, CredSSPClaves SSH, contraseñaClaves SSH, contraseña
MultiplataformaSolo WindowsWindows, Linux, macOSSolo Windows (servidor)
Versión de PowerShell5.1+7.0+ requeridoCualquiera (solo shell SSH)
CifradoHTTPS o a nivel de mensajeSiempre cifradoSiempre cifrado
Doble saltoCredSSP o delegación KerberosReenvío de agente SSHReenvío de agente SSH
Integración con dominioAD/Kerberos nativoGestión manual de clavesGestión manual de claves
Gestión por GPOSoporte completoLimitadoLimitado
Ideal paraEntornos solo WindowsEntornos con SO mixtoAdmins Linux gestionando Windows

Escenario del Mundo Real

Imagina que eres un administrador de sistemas gestionando más de 50 servidores Windows en tres entornos — Desarrollo, Staging y Producción — además de un puñado de máquinas Linux ejecutando proxies inversos Nginx. Así es como estructurarías tu flujo de trabajo con PowerShell Remoting:

# Definir grupos de servidores
$servidoresDev = Get-Content "C:\ListasServidores\dev.txt"
$servidoresStaging = Get-Content "C:\ListasServidores\staging.txt"
$servidoresProd = Get-Content "C:\ListasServidores\prod.txt"

# Crear sesiones persistentes con credenciales almacenadas
$cred = Import-Clixml "$HOME\admin-cred.xml"
$sesionesDev = New-PSSession -ComputerName $servidoresDev -Credential $cred
$sesionesStaging = New-PSSession -ComputerName $servidoresStaging -Credential $cred

# Verificación de salud matutina en todos los servidores de desarrollo
$reporteSalud = Invoke-Command -Session $sesionesDev -ScriptBlock {
    [PSCustomObject]@{
        Servidor   = $env:COMPUTERNAME
        Uptime     = (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
        CPUPorcent = (Get-CimInstance Win32_Processor).LoadPercentage
        LibreGB    = [math]::Round((Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'").FreeSpace / 1GB, 2)
        Servicios  = (Get-Service | Where-Object { $_.StartType -eq "Automatic" -and $_.Status -ne "Running" }).Count
    }
}

$reporteSalud | Format-Table Servidor, Uptime, CPUPorcent, LibreGB, Servicios -AutoSize

# Desplegar un hotfix a staging con concurrencia limitada
Invoke-Command -Session $sesionesStaging -ThrottleLimit 5 -ScriptBlock {
    Start-Process msiexec.exe -ArgumentList "/i C:\Deploy\hotfix-kb123.msi /quiet" -Wait
    Write-Output "$env:COMPUTERNAME — Hotfix instalado"
}

# Verificar proxies Linux sobre SSH
$sesionesLinux = New-PSSession -HostName "proxy01","proxy02" -UserName admin -SSHTransport
Invoke-Command -Session $sesionesLinux -ScriptBlock {
    systemctl is-active nginx
    curl -s -o /dev/null -w "%{http_code}" http://localhost
}

Este patrón mantiene las sesiones abiertas durante la duración de tu trabajo, minimiza la sobrecarga de autenticación y te permite apuntar a grupos de entornos específicos con ejecución limitada.

Errores Comunes y Casos Especiales

  • Bloqueo de firewall: WinRM usa el puerto 5985 (HTTP) y 5986 (HTTPS). Si el remoting falla silenciosamente, verifica tanto el Firewall de Windows como cualquier firewall de red entre cliente y servidor.
  • Reinicio de TrustedHosts: Establecer TrustedHosts con Set-Item reemplaza toda la lista. Usa -Concatenate para agregar: Set-Item WSMan:\localhost\Client\TrustedHosts -Value "NUEVOSERVIDOR" -Concatenate.
  • MaxMemoryPerShellMB: El límite predeterminado (1024 MB) puede causar que las sesiones se caigan durante operaciones intensivas en memoria. Auméntalo con Set-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB 2048.
  • Fallo de doble salto: Acceder a recursos de red desde una sesión remota falla por defecto. Usa CredSSP, delegación restringida de Kerberos o delegación restringida basada en recursos para resolver esto.
  • Límites de sesión: WinRM tiene un límite predeterminado de 25 shells concurrentes por usuario. En entornos grandes, incrementa MaxShellsPerUser en la configuración de WinRM.
  • Desfase de zona horaria: Las marcas de tiempo devueltas desde sesiones remotas usan la zona horaria del servidor remoto. Usa [DateTime]::UtcNow para consistencia en entornos multi-región.
  • Ruta del subsistema SSH: En Windows, la ruta del subsistema en sshd_config debe usar el formato de nombre corto 8.3 (progra~1) o la ruta completa sin espacios.
  • Límites de serialización: Los objetos devueltos desde sesiones remotas están deserializados — pierden sus métodos. Lo que regresa es una instantánea, no un objeto vivo. Planifica tus bloques de script para extraer los datos que necesitas en el lado remoto.
  • Discrepancia de versión de PowerShell: Si la máquina remota ejecuta PowerShell 5.1 y el cliente ejecuta PowerShell 7, no todos los cmdlets estarán disponibles. Prueba con -ConfigurationName PowerShell.7 para endpoints de PS7.

Resumen

  • Enable-PSRemoting es el comando integral para configurar WinRM en cualquier máquina Windows.
  • TrustedHosts debe configurarse en el cliente para conexiones de grupo de trabajo o entre dominios.
  • El transporte HTTPS debe usarse en producción para cifrar el tráfico de remoting de extremo a extremo.
  • Invoke-Command es la herramienta principal para ejecución paralela en múltiples servidores; Enter-PSSession es ideal para resolución de problemas interactiva.
  • La gestión de credenciales debe usar Export-Clixml, el Administrador de Credenciales o un almacén de secretos — nunca contraseñas escritas directamente en código.
  • CredSSP o la delegación restringida de Kerberos resuelve el problema del doble salto.
  • El remoting basado en SSH en PowerShell 7+ habilita la gestión multiplataforma de Linux y macOS desde los mismos scripts.
  • Los endpoints JEA proporcionan remoting con privilegios mínimos para administración delegada.
  • Ten cuidado con los límites de sesión, el comportamiento de serialización y las reglas de firewall a medida que tu entorno crece.

Artículos Relacionados