Короткий ответ
WinRM нужен для Invoke-Command, Ansible, MECM. Он не должен слушаться на 0.0.0.0 с интернета на 5985/TCP (HTTP) или 5986/TCP (HTTPS). Схема: сертификат, listener HTTPS, firewall RemoteAddress = admin/VPN/jump, HTTP listener удалить или оставить только localhost/admin-сеть. Enable-PSRemoting без сужения — слишком широко. TrustedHosts=* на WS-042 — запрещённая привычка.
Не отключайте firewall, чтобы WinRM «заработал». Не открывайте 5985 рядом с уже закрытым 3389. Включайте PowerShell logging на целях.
Симптомы и как отличить
winrm enumerate winrm/config/listenerпоказывает HTTP :5985 на всех интерфейсах.- С LTE
Test-NetConnection <WAN> -Port 5985True. - Клиенты с
-SkipCACheck -SkipCNCheck -SkipRevocationCheck. - NTLM к WinRM по IP.
| Ситуация | Иное |
|---|---|
| 5985 внутри jump-VLAN | допустимо как переход к HTTPS |
| Служба WinRM Stopped, управление только RDP | осознанно, не «безопасность через obscurity» |
| Firewall off | firewall |
| SMB ADMIN$ | шары |
Возможные причины
Enable-PSRemoting -Forceна сервере с белым IP.- GPO WinRM без фильтра IPv4 filter / без HTTPS.
- Облачный NSG 5985 Any.
- TrustedHosts звёздочка для лабораторных скриптов, уехавших в прод.
- Самоподписанный сертификат + SkipCNCheck в каждом скрипте.
Диагностика
На целевом сервере:
Get-Service WinRM
winrm get winrm/config
winrm enumerate winrm/config/listener
Get-NetFirewallRule -DisplayName '*WinRM*' | Get-NetFirewallAddressFilter |
Format-Table InstanceID, RemoteAddress
Get-NetTCPConnection -LocalPort 5985,5986 -State Listen -ErrorAction SilentlyContinue
Get-Item WSMan:\localhost\Client\TrustedHosts
Get-PSSessionConfiguration | Format-Table Name, PermissionС jump и с LTE:
Test-NetConnection SRV-APP01.contoso.example -Port 5986
Test-NetConnection SRV-APP01.contoso.example -Port 5985
Test-NetConnection <WAN-IP> -Port 5985Сертификат listener: Thumbprint в enumerate, сверка CN/SAN в Get-ChildItem Cert:\LocalMachine\My.
Решение
Сценарий A. HTTPS listener, HTTP убрать с внешних NIC
- Сертификат Computer из PKI
contoso.exampleс FQDN сервера, EKUs Server Authentication. - Создать HTTPS listener (штатный
New-Item WSMan:\localhost\Listener/winrm createпо документации для вашей версии, с указанием Thumbprint и Transport=HTTPS). - Firewall:
New-NetFirewallRule -Name 'WinRM-HTTPS-Admin' -DisplayName 'WinRM HTTPS from admin' `
-Direction Inbound -Protocol TCP -LocalPort 5986 -RemoteAddress 10.0.10.0/24,10.8.0.0/24 `
-Action Allow -Profile Domain
Get-NetFirewallRule | Where-Object DisplayName -match 'WinRM' |
ForEach-Object { Set-NetFirewallRule -Name $_.Name -RemoteAddress 10.0.10.0/24,10.8.0.0/24 }Подставьте сети. Удалите/отключите правило Allow WinRM Any.
- Удалите HTTP listener, если политика «только HTTPS»:
Get-ChildItem WSMan:\localhost\Listener
# Remove-Item конкретного HTTP listener по его имени после проверки HTTPSСценарий B. Пока только HTTP в admin-сети
Если PKI не готова: HTTP только с jump CIDR, NTLM снижать, Kerberos с FQDN. Срок: дата перехода на 5986. Не публиковать 5985 в NAT.
Сценарий C. Клиент jump
Test-WSMan -UseSSL -ComputerName SRV-APP01.contoso.example
Invoke-Command -ComputerName SRV-APP01.contoso.example -UseSSL -ScriptBlock { hostname }TrustedHosts не нужен при Kerberos/HTTPS с правильным именем в домене. Звезда запрещена.
GPO: Allow remote server management through WinRM = Enabled, IPv4 filter = admin диапазоны (синтаксис фильтра в ADMX: диапазоны через минус, читайте подсказку политики).
Сценарий D. Сессии и права
Get-PSSessionConfiguration Microsoft.PowerShell — кто имеет Execute. Не Everyone. Отдельная группа CONTOSO\WinRM-Admins. JEA — следующий уровень, не обязателен в первый день, но лучше DA на каждом хосте.
Сертификаты WinRM выпускайте из PKI contoso.example шаблоном Computer с автоэнролом на серверы, не самоподписанными на каждый хост. На DC01 SPN WSMAN/ должен быть на самом компьютере DC, без дублей. Клиенты jump подключаются к FQDN. WS-042 пользователя WinRM с WAN не должен слушаться вовсе: GPO filter IPv4 пустой + firewall block, либо служба не нужна. Ansible/MECM переведите на HTTPS в той же заявке, что listener, иначе HTTP Any вернётся «потому что playbook». TrustedHosts на jump — только если есть workgroup-исключение с датой вывода, не *.
Проверьте после gpupdate: winrm enumerate winrm/config/listener и Test-NetConnection с LTE на 5985.
Не оставляйте -SkipCACheck -SkipCNCheck в scheduled tasks jump-хоста: это обход PKI, эквивалентный HTTP. После выпуска шаблона Computer обновите клиентские скрипты в репозитории автоматизации.
На dual-homed сервере привяжите listener к LAN IP, не к *, чтобы WAN NIC не принимал 5986 даже при ошибке firewall.
Как проверить, что проблема устранена
- С LTE 5985/5986 на WAN False.
- С jump HTTPS
Test-WSMan -UseSSLок. winrm enumerate listener— HTTPS, HTTP нет или только localhost.- TrustedHosts пуст или явный список lab, не
*. - Firewall RemoteAddress не Any.
- 4104 на целевом хосте при тестовом
Invoke-Command.
Если не помогло
- Kerberos: SPN
WSMAN/SRV-APP01.contoso.example— смотритеsetspn -Q WSMAN/SRV-APP01.contoso.example. Дубли ломают. - Сертификат не на тот CN / истек / нет в Root на клиенте.
- NLA/прокси: WinRM не через системный прокси иногда — обход для admin-сети.
- GPO снова включает HTTP Any — выровняйте.
- Ansible
winrmscheme http — переведите на https.
Профилактика
- Эталон: WinRM HTTPS в золотом образе + GPO filter.
- Мониторинг listen 5985 с не-admin интерфейсов.
- Запрет TrustedHosts=* в регламенте.
- Сессии с privileged-учёток только с jump.
- TLS 1.2+ на Schannel, см. TLS.
FAQ
5985 vs 5986
5985 HTTP, 5986 HTTPS. Цель — 5986. 5985 только в изолированной admin-сети на время миграции.
Enable-PSRemoting включает firewall Any?
Создаёт правила; их нужно сразу сузить. Не считайте команду финалом hardening.
Нужен ли WinRM на WS-042 пользователя?
Часто нет. Если нужен Intune/MECM — отдельная политика, всё равно не WAN.
Basic auth
Не включайте Basic на HTTP. Даже на HTTPS лучше Kerberos.
Можно ли слушать только на одном IP?
Listener можно привязать к Address IP (не *). Полезно на dual-homed. Документируйте.
Double hop
Копируйте файлы через jump, используйте CredSSP только точечно с пониманием риска, или переработайте скрипт (выполнять на целевом, не тянуть третий хост).