PowerShell Remoting: WinRM и SSH для удалённого управления

Архитектура PowerShell Remoting

PowerShell Remoting — технология удалённого выполнения команд, построенная на протоколе WS-Management (WinRM) или SSH. Она позволяет администратору запускать команды на одном или нескольких удалённых компьютерах одновременно, получать результаты в виде десериализованных объектов PowerShell и управлять целыми парками серверов из единой консоли.

Два основных транспорта:

  • WinRM (Windows Remote Management) — стандарт для Windows-инфраструктуры. Использует HTTP (порт 5985) или HTTPS (порт 5986). Поддерживает аутентификацию Kerberos, NTLM, CredSSP, Certificate
  • SSH (Secure Shell) — кроссплатформенный транспорт, доступный с PowerShell 6+. Работает на Windows, Linux и macOS. Использует стандартный порт 22

Основные командлеты для работы с remoting:

  • Enter-PSSession — интерактивная сессия на удалённом компьютере
  • Invoke-Command — выполнение команд на одном или нескольких компьютерах
  • New-PSSession — создание постоянной сессии для повторного использования
  • Copy-Item -ToSession / -FromSession — копирование файлов через remoting

Настройка WinRM

По умолчанию WinRM включён на серверных версиях Windows начиная с Server 2012, но на клиентских ОС его нужно включать вручную.

Быстрая настройка WinRM

Для быстрого включения WinRM со стандартными параметрами:

# Включение WinRM (создаёт HTTP-listener на порту 5985)
Enable-PSRemoting -Force

# Проверка конфигурации
winrm get winrm/config
winrm enumerate winrm/config/listener

# Проверка службы
Get-Service WinRM

# Тест подключения
Test-WSMan -ComputerName server01.corp.local

Команда Enable-PSRemoting выполняет следующие действия: запускает службу WinRM, устанавливает автозапуск, создаёт HTTP-listener, настраивает исключения в брандмауэре и регистрирует конфигурации сессий PowerShell.

Настройка HTTPS для WinRM

Для безопасного подключения через WinRM рекомендуется использовать HTTPS. Это шифрует трафик и защищает от перехвата:

# Создание самоподписанного сертификата (для тестов)
$cert = New-SelfSignedCertificate -DnsName "server01.corp.local" `
  -CertStoreLocation Cert:\LocalMachine\My `
  -NotAfter (Get-Date).AddYears(5)

# Создание HTTPS-listener
New-Item WSMan:\localhost\Listener `
  -Transport HTTPS `
  -Address * `
  -CertificateThumbprint $cert.Thumbprint `
  -Force

# Открытие порта в брандмауэре
New-NetFirewallRule -DisplayName "WinRM HTTPS" `
  -Direction Inbound -Protocol TCP `
  -LocalPort 5986 -Action Allow

# Проверка listener'ов
winrm enumerate winrm/config/listener

# Подключение по HTTPS
Enter-PSSession -ComputerName server01.corp.local `
  -UseSSL -Credential (Get-Credential)

В продакшен-среде используйте сертификаты от корпоративного CA (Active Directory Certificate Services), а не самоподписанные. Разверните сертификаты через групповую политику для автоматизации.

Массовая настройка через GPO

Для централизованной настройки WinRM в домене используйте Group Policy:

# Путь в GPO:
# Computer Configuration → Policies → Administrative Templates →
# Windows Components → Windows Remote Management (WinRM) → WinRM Service

# Ключевые параметры:
# 1. Allow remote server management through WinRM: Enabled
#    IPv4 filter: * (все адреса)
# 2. Allow Basic authentication: Disabled (в доменной среде)
# 3. Allow CredSSP authentication: по необходимости

# Также настройте службу WinRM:
# Computer Configuration → Policies → Windows Settings →
# Security Settings → System Services →
# Windows Remote Management (WS-Management): Automatic

# Брандмауэр через GPO:
# Computer Configuration → Policies → Windows Settings →
# Security Settings → Windows Firewall → Inbound Rules
# Предопределённое правило: Windows Remote Management

PowerShell Remoting через SSH

SSH-транспорт — кроссплатформенное решение для управления гетерогенной инфраструктурой (Windows + Linux) из единой консоли PowerShell.

Установка OpenSSH на Windows Server

Начиная с Windows Server 2019, OpenSSH доступен как компонент:

# Установка OpenSSH Server
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

# Запуск и автозапуск службы
Start-Service sshd
Set-Service sshd -StartupType Automatic

# Брандмауэр
New-NetFirewallRule -DisplayName "OpenSSH Server" `
  -Direction Inbound -Protocol TCP `
  -LocalPort 22 -Action Allow

Конфигурация SSH для PowerShell subsystem

Для работы PowerShell Remoting через SSH необходимо зарегистрировать PowerShell как SSH subsystem. Отредактируйте файл C:\ProgramData\ssh\sshd_config:

# Добавьте строку в sshd_config:
Subsystem powershell c:/progra~1/powershell/7/pwsh.exe -sshs -NoLogo -NoProfile

# Для аутентификации по ключам:
PubkeyAuthentication yes
PasswordAuthentication yes

# Перезапуск SSH
Restart-Service sshd

На Linux-серверах с установленным PowerShell 7:

# /etc/ssh/sshd_config
Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile

# Перезапуск
sudo systemctl restart sshd

Подключение через SSH:

# По паролю
Enter-PSSession -HostName linux-srv01.corp.local -UserName admin -SSHTransport

# По ключу
Enter-PSSession -HostName linux-srv01.corp.local `
  -UserName admin `
  -KeyFilePath ~/.ssh/id_rsa `
  -SSHTransport

# Выполнение команд на нескольких серверах (Windows + Linux)
Invoke-Command -HostName server01,linux-srv01,linux-srv02 `
  -UserName admin -SSHTransport `
  -ScriptBlock { Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 }

Продвинутые сценарии использования

PowerShell Remoting предоставляет мощные возможности для автоматизации управления инфраструктурой.

Постоянные сессии и параллельное выполнение

Используйте постоянные сессии для серии команд на одних и тех же серверах:

# Создание сессий ко всем серверам
$servers = Get-ADComputer -Filter 'OperatingSystem -like "*Server*"' |
  Select-Object -ExpandProperty DnsHostName
$sessions = New-PSSession -ComputerName $servers -ThrottleLimit 32

# Выполнение команды на всех серверах параллельно
Invoke-Command -Session $sessions -ScriptBlock {
  [PSCustomObject]@{
    Hostname = $env:COMPUTERNAME
    Uptime   = (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
    RAM_Free = [math]::Round((Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory / 1MB, 2)
    CPU_Load = (Get-CimInstance Win32_Processor).LoadPercentage
    Disk_C   = [math]::Round((Get-PSDrive C).Free / 1GB, 2)
  }
} | Sort-Object Hostname | Format-Table -AutoSize

# Копирование файла на все серверы
$sessions | ForEach-Object {
  Copy-Item -Path "C:\Scripts\monitor.ps1" `
    -Destination "C:\Scripts\" -ToSession $_
}

# Закрытие сессий
$sessions | Remove-PSSession

PowerShell 7: ForEach-Object -Parallel

В PowerShell 7 появилась нативная параллелизация через ForEach-Object -Parallel:

# Параллельная проверка служб на серверах
$servers = @("srv01","srv02","srv03","srv04","srv05")
$servers | ForEach-Object -Parallel {
  Invoke-Command -ComputerName $_ -ScriptBlock {
    Get-Service -Name W3SVC, MSSQLSERVER, WinRM |
      Select-Object @{N='Server';E={$env:COMPUTERNAME}}, Name, Status
  }
} -ThrottleLimit 10 | Format-Table -AutoSize

Just Enough Administration (JEA)

JEA ограничивает возможности удалённой сессии, предоставляя пользователю только определённые командлеты и функции. Это реализация принципа наименьших привилегий для PowerShell Remoting.

Создание конфигурации роли

Создайте файл роли (.psrc), определяющий доступные команды:

# Создание шаблона файла роли
New-PSRoleCapabilityFile -Path "C:\JEA\DNSAdmin.psrc"

# Отредактируйте файл:
@{
  # Модули для импорта
  ModulesToImport = @('DnsServer')

  # Разрешённые командлеты
  VisibleCmdlets = @(
    'Get-DnsServerZone',
    'Get-DnsServerResourceRecord',
    @{ Name = 'Add-DnsServerResourceRecordA';
       Parameters = @{ Name = 'ZoneName'; ValidateSet = 'corp.local' } },
    @{ Name = 'Remove-DnsServerResourceRecord';
       Parameters = @{ Name = 'ZoneName'; ValidateSet = 'corp.local' } }
  )

  # Разрешённые функции
  VisibleFunctions = @('Get-Date', 'Select-Object', 'Format-Table')

  # Разрешённые внешние команды
  VisibleExternalCommands = @('nslookup.exe', 'ipconfig.exe')
}

Регистрация конфигурации сессии

Создайте и зарегистрируйте конфигурацию сессии (.pssc):

# Создание файла конфигурации сессии
New-PSSessionConfigurationFile -Path "C:\JEA\DNSAdmin.pssc" `
  -SessionType RestrictedRemoteServer `
  -RunAsVirtualAccount `
  -RoleDefinitions @{
    'CORP\DNS-Operators' = @{ RoleCapabilities = 'DNSAdmin' }
  } `
  -TranscriptDirectory "C:\JEA\Transcripts"

# Регистрация
Register-PSSessionConfiguration -Name DNSAdmin `
  -Path "C:\JEA\DNSAdmin.pssc" -Force

# Подключение к JEA-сессии
Enter-PSSession -ComputerName dc01.corp.local `
  -ConfigurationName DNSAdmin `
  -Credential (Get-Credential)

# Проверка доступных команд в JEA-сессии
Get-Command

JEA-сессия работает от имени виртуальной учётной записи с правами локального администратора, но пользователь может выполнять только разрешённые команды. Все действия логируются в Transcript-файлах.

Диагностика проблем подключения

Типичные ошибки при работе с PowerShell Remoting и их решения:

# Ошибка: WinRM cannot complete the operation
# Решение 1: Проверка службы
Get-Service WinRM -ComputerName server01

# Решение 2: Проверка listener
winrm enumerate winrm/config/listener

# Решение 3: Проверка доступности порта
Test-NetConnection -ComputerName server01 -Port 5985

# Ошибка: Access Denied
# Проверка: пользователь должен быть в группе Remote Management Users
Get-LocalGroupMember -Group "Remote Management Users" -ComputerName server01

# Ошибка: The WinRM client cannot process the request (для не-доменных машин)
# Решение: добавьте сервер в TrustedHosts
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "192.168.1.100" -Force
# Или для всех (не рекомендуется в продакшене)
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*" -Force

# Детальная диагностика с трассировкой
$sess = New-PSSession -ComputerName server01 -Verbose

# Проверка конфигурации SPN для Kerberos
setspn -L server01$

Проблемы с CredSSP и Double-Hop

Классическая проблема double-hop: при подключении к серверу A через remoting, сервер A не может аутентифицироваться на сервере B (например, при доступе к файловой шаре):

# Вариант 1: CredSSP (менее безопасный)
# На клиенте:
Enable-WSManCredSSP -Role Client -DelegateComputer server01.corp.local
# На сервере:
Enable-WSManCredSSP -Role Server
# Подключение:
Enter-PSSession -ComputerName server01 -Authentication CredSSP -Credential (Get-Credential)

# Вариант 2: Kerberos Constrained Delegation (рекомендуется)
# Настройка через AD:
Set-ADComputer -Identity server01 `
  -PrincipalsAllowedToDelegateToAccount (Get-ADComputer server02)

# Вариант 3: Передача учётных данных через переменную
$cred = Get-Credential
Invoke-Command -ComputerName server01 -ScriptBlock {
  param($c)
  New-PSDrive -Name Z -PSProvider FileSystem `
    -Root "\\fileserver\share" -Credential $c
} -ArgumentList $cred

Часто задаваемые вопросы

Да, начиная с PowerShell 7. На Linux-сервере нужно установить PowerShell 7 и настроить SSH subsystem в sshd_config. После этого используйте Enter-PSSession -HostName linux-srv -UserName admin -SSHTransport или Invoke-Command с параметром -HostName. WinRM-транспорт на Linux не поддерживается.

Enter-PSSession создаёт интерактивную сессию на одном компьютере — вы работаете в ней как в локальном терминале. Invoke-Command выполняет блок команд на одном или нескольких компьютерах неинтерактивно и возвращает результаты. Для автоматизации всегда используйте Invoke-Command, для ручной диагностики — Enter-PSSession.

Основные меры: используйте HTTPS вместо HTTP, ограничьте доступ через брандмауэр по IP-адресам, настройте JEA для ограничения доступных команд, включите аудит PowerShell Script Block Logging и Transcription, используйте группу Remote Management Users вместо добавления всех в локальные администраторы. В GPO отключите Basic-аутентификацию и CredSSP, если они не нужны.

Для чисто Windows-инфраструктуры с Active Directory оптимален WinRM — он работает из коробки, поддерживает Kerberos SSO и GPO-управление. Для гетерогенной среды (Windows + Linux) или подключений через интернет выбирайте SSH — он безопаснее по умолчанию, поддерживает аутентификацию по ключам и не требует дополнительной настройки на Linux.

По умолчанию WinRM ограничивает количество одновременных подключений. Измените лимиты через Set-Item WSMan:\localhost\Shell\MaxShellsPerUser -Value 50 и Set-Item WSMan:\localhost\Shell\MaxConcurrentUsers -Value 25. Для Invoke-Command используйте параметр -ThrottleLimit (по умолчанию 32).

Нужна помощь с настройкой?

Специалисты АйТи Фреш помогут с внедрением и настройкой — 15+ лет опыта, обслуживание от 15 000 ₽/мес

📞 Связаться с нами
#PowerShell Remoting#WinRM#SSH PowerShell#удалённое управление PowerShell#Enter-PSSession#Invoke-Command#JEA PowerShell#PowerShell SSH
Комментарии 0

Оставить комментарий

загрузка...