PowerShell Remoting: WinRM и SSH для удалённого управления — АйТи Фреш

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

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

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

Транспортов два, и они очень разные по сфере применения:

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

Четыре командлета, которые покрывают 95% задач remoting:

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

Настройка WinRM

WinRM включён по умолчанию на серверных Windows начиная с Server 2012. На клиентских ОС — Windows 10, 11 — его придётся включать руками. Мы не раз сталкивались с ситуацией, когда об этом забывают и потом удивляются ошибкам подключения.

Быстрая настройка 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 — трафик будет зашифрован и защищён от перехвата. HTTP в открытой сети — плохая идея, особенно если речь идёт о передаче учётных данных:

# Создание самоподписанного сертификата (для тестов)
$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 (Just Enough Administration) ограничивает удалённую сессию так, что пользователь видит только конкретные командлеты и функции — и ничего лишнего. Это прямая реализация принципа наименьших привилегий для 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-файлы — потом всегда можно поднять историю и разобраться, что и кто делал.

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

Разберём типичные ошибки, с которыми сталкиваемся сами и которые регулярно видим у клиентов:

# Ошибка: 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 не поддерживается — только SSH.

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

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

Если вся инфраструктура — Windows с Active Directory, берите WinRM. Kerberos SSO, управление через GPO, работает из коробки — что ещё нужно? Но как только в сети появляются Linux-машины или нужно подключаться через интернет, я бы сразу смотрел в сторону SSH. Безопаснее по умолчанию, аутентификация по ключам, и никаких плясок с бубном на стороне Linux.

WinRM по умолчанию довольно скромен по лимитам одновременных подключений — мы не раз упирались в этот потолок при массовых операциях на 30+ серверах. Поправить просто: 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

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

загрузка...

Подпишитесь на рассылку ITfresh

Каждую неделю мы выпускаем практические гайды для руководителей IT и системных администраторов. Это не просто теория! Здесь вы найдёте всё: безопасность, 1С, миграции, резервные копии и проверенные лайфхаки из наших реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.