Windows Server для самых маленьких. Часть 26: Как работают NPS и RADIUS?

Все части серии «Windows Server для самых маленьких»

Точка доступа Wi-Fi, коммутатор с портами в переговорных, VPN-шлюз на границе сети — у всех одна задача: пустить своих и не пустить чужих. Ни у одного из них нет базы пользователей, и быть не должно: пользователи — в каталоге. Между сетевым оборудованием и каталогом нужен переводчик, который примет запрос «вот человек с таким именем и таким доказательством, пускать?» и ответит «да, в такой VLAN» или «нет». Этот переводчик — RADIUS, протокол, который появился в 1991 году у производителя модемных пулов и пережил всё, что должно было его заменить, а в Windows Server его реализует роль Network Policy Server.

Эта часть — о протоколе и о сервере; следующие две — о двух его главных применениях, Wi-Fi и VPN.


RADIUS

Remote Authentication Dial-In User Service, RFC 2865 (аутентификация и авторизация) и 2866 (учёт). Участники: NAS (network access server — точка доступа, коммутатор, шлюз; в терминах RADIUS он клиент) и сервер RADIUS. Между ними UDP — без соединений и повторной передачи, поэтому NAS сам повторяет запрос, не дождавшись ответа. Порт 1812 для аутентификации и 1813 для учёта; первые реализации заняли 1645 и 1646, и NPS по умолчанию слушает все четыре. Третье, что связывает стороны, — общий секрет, строка, известная обеим.

Типы пакетов аутентификации и их коды в заголовке: Access-Request (1), Access-Accept (2), Access-Reject (3), Access-Challenge (11):

 NAS                                     сервер RADIUS
  │                                           │
  ├─ Access-Request ─────────────────────────►│  User-Name, NAS-IP-Address, NAS-Port-Type,
  │                                           │  Calling-Station-Id (MAC клиента), Called-Station-Id
  │                                           │  (MAC точки:SSID), и доказательство: User-Password
  │                                           │  или EAP-Message
  │◄─ Access-Challenge ───────────────────────┤  «спроси ещё»: следующий шаг EAP; может повториться
  ├─ Access-Request ─────────────────────────►│  десяток раз
  │◄─ Access-Accept ──────────────────────────┤  пускать; атрибуты: VLAN, таймауты, ключи шифрования
  │    или Access-Reject                      │  не пускать; без объяснений клиенту

Пакет — заголовок (код, идентификатор, длина, 16-байтовый Authenticator) и список атрибутов в формате тип-длина-значение; максимальная длина пакета — 4096 байт, одного атрибута — 253 байта данных. RFC 2865 определяет 63 атрибута, следующие RFC добавили ещё, а тип 26, Vendor-Specific, вмещает атрибуты производителей: Microsoft (MS-MPPE-Send-Key, MS-CHAP-*, RFC 2548), Cisco (cisco-av-pair) и так далее.

Защита пакета — общий секрет и Authenticator. В запросе Authenticator случайный, и пароль в User-Password закрывается XOR с MD5 от секрета и Authenticator (MD5 — хеш-функция, дающая 16 байт от любых данных); в ответе Authenticator — MD5 от всего ответа вместе с Authenticator запроса и секретом, и NAS по нему проверяет, что ответ настоящий. Для девяностых этого хватало, сегодня — нет. В 2024 году опубликовали атаку Blast-RADIUS: злоумышленник посередине между NAS и сервером подбирает коллизию MD5 и превращает Access-Reject в Access-Accept. Защита — атрибут Message-Authenticator (тип 80, RFC 2869): HMAC-MD5 от всего пакета с ключом-секретом, то есть подпись, которую без секрета не подделать. Для EAP он обязателен по RFC 3579, и NPS требует его в любом запросе с EAP; уязвимы запросы без EAP — PAP, MS-CHAP. Обновления Windows с июля 2024 года добавили в NPS проверки, но по умолчанию они выключены: Microsoft советует требовать Message-Authenticator от каждого клиента (requireauthattrib) и включить limitProxyState и requireMsgAuth (о них ниже). Общее правило остаётся прежним: RADIUS не ходит через недоверенные сети, а если должен — внутри IPsec (часть 19 сетевой серии). Есть и RADIUS поверх TLS — RadSec (RFC 6614): тот же протокол внутри TLS-соединения по TCP 2083, где секрет уже не играет роли, — но NPS его не умеет.

EAP внутри RADIUS (RFC 3579). Для Wi-Fi и проводного 802.1X доказательство — не пароль в атрибуте, а разговор по протоколу EAP (Extensible Authentication Protocol, RFC 3748): рамка «запрос — ответ», внутри которой едет выбранный метод проверки, каждый со своим номером типа. Говорят клиент (supplicant) и сервер RADIUS, а NAS — лишь посредник. 802.1X — стандарт IEEE, по которому порт коммутатора или ассоциация Wi-Fi не пропускает ничего, кроме кадров аутентификации (EAPOL — EAP over LAN), пока она не завершилась. Кадры EAP точка доступа переупаковывает из EAPOL в атрибуты EAP-Message и обратно, не понимая содержимого. Разговор занимает десяток обменов Access-Request / Access-Challenge: сообщения TLS не помещаются в один пакет и режутся на фрагменты по размеру из атрибута Framed-MTU, который присылает NAS (точки доступа из примеров ниже — 1002 байта). В конце, если всё хорошо, сервер присылает Access-Accept с атрибутами MS-MPPE-Recv-Key и MS-MPPE-Send-Key — материалом, из которого NAS и клиент выводят ключи шифрования для этого сеанса (в Wi-Fi это PMK, с которого начинается четырёхстороннее рукопожатие из части 3 сетевой серии). Пароль пользователя при этом не покидает TLS-туннеля между клиентом и сервером RADIUS (часть 23 сетевой серии), и NAS его не видит никогда.

 клиент              точка доступа (NAS)             NPS                 контроллер
   │                         │                         │                         │
   ├─ EAPOL: EAP-Response ──►├─ Access-Request ───────►│                         │
   │◄─ EAPOL: EAP-Request ───┤◄─ Access-Challenge ─────┤                         │
   │    … десять обменов: TLS-туннель PEAP, внутри EAP-MSCHAPv2 …                │
   │                         │                         ├─ проверка ответа ──────►│
   │                         │                         │◄─ да / нет ─────────────┤
   │◄─ EAP-Success ──────────┤◄─ Access-Accept ────────┤                         │
   │                         │   MS-MPPE-*-Key, VLAN   │                         │

Учёт (accounting) — отдельные пакеты Accounting-Request (код 4) со Start, Interim-Update, Stop и счётчиками байтов и времени; сервер отвечает Accounting-Response (код 5) и пишет в журнал.


NPS

Роль ставится на сервер с графической оболочкой: в варианте Server Core роли NPAS нет. Традиционно NPS живёт на контроллере, потому что проверяет учётные данные по каталогу; для серии — отдельный nps1.corp.example.com, рядовой сервер:

PS C:\> Install-WindowsFeature NPAS -IncludeManagementTools
PS C:\> Get-Service IAS | Select-Object Status, StartType

 Status StartType
 ------ ---------
Running Automatic

Служба называется IAS — Internet Authentication Service, имя роли до 2008 года; она работает внутри svchost от LocalSystem с отложенным запуском, поэтому после перезагрузки RADIUS начинает отвечать через минуту-две после старта системы.

NPS должен читать свойства удалённого доступа у учётных записей (вкладка Dial-in), и это право у группы RAS and IAS Servers (доменная локальная, RID 553). Регистрация NPS в домене — это добавление учётной записи компьютера в эту группу:

PS C:\> netsh nps add registeredserver
PS C:\> Get-ADGroupMember 'RAS and IAS Servers' | Select-Object Name

Name
----
NPS1

Документация требует регистрации без исключений. Состояние показывает netsh nps show registeredserver; у NPS на контроллере домена, который в группу не добавлен, он отвечает так — и при этом пускает пользователей, но его политики свойства Dial-in и не читают (флаг «игнорировать», см. ниже):

PS C:\> netsh nps show registeredserver

Server registration:
---------------------------------------------------------
Status = Un-registered

Ok.

Модуль NPS маленький — клиенты RADIUS, экспорт и импорт:

PS C:\> Get-Command -Module NPS | Select-Object -ExpandProperty Name
Export-NpsConfiguration
Get-NpsRadiusClient
Get-NpsSharedSecretTemplate
Import-NpsConfiguration
New-NpsRadiusClient
Remove-NpsRadiusClient
Set-NpsRadiusClient

Командлетов для политик, групп удалённых серверов и создания шаблонов секретов нет: это консоль или netsh nps. В манифесте модуля не указан Core, так что в PowerShell 7 он загружается через слой совместимости — из Windows PowerShell 5.1 в фоновом сеансе.


Клиенты

Каждое устройство, которое будет присылать запросы, регистрируется с адресом и секретом; запрос с незнакомого адреса NPS отбрасывает и пишет событие 13 в журнал System:

PS C:\> New-NpsRadiusClient -Name 'ap-floor1' -Address 192.168.1.5 -SharedSecret (Read-Host 'Secret') -AuthAttributeRequired $true
PS C:\> New-NpsRadiusClient -Name 'sw-core' -Address 192.168.1.2 -SharedSecret (Read-Host 'Secret') -VendorName 'Cisco' -AuthAttributeRequired $true
PS C:\> New-NpsRadiusClient -Name 'vpn-gw' -Address 192.168.1.1 -SharedSecret (Read-Host 'Secret')
PS C:\> Get-NpsRadiusClient | Format-Table Name, Address, Enabled, VendorName, AuthAttributeRequired -AutoSize

Name      Address     Enabled VendorName      AuthAttributeRequired
----      -------     ------- ----------      ---------------------
ap-floor1 192.168.1.5    True RADIUS Standard                 False
ap-floor2 192.168.1.6    True RADIUS Standard                 False
ap-floor3 192.168.1.7    True RADIUS Standard                 False
vpn-gw    192.168.1.1    True RADIUS Standard                 False

Вывод — с сервера, который настраивали в консоли: все клиенты со стандартным словарём и без AuthAttributeRequired. Это умолчание, и ровно это советует исправить статья Microsoft о Blast-RADIUS: AuthAttributeRequired (в netsh — requireauthattrib) заставляет NPS отбрасывать запросы этого клиента без Message-Authenticator (событие 17), а без него NPS проверяет атрибут, только если тот пришёл. Перед включением стоит убедиться, что NAS его шлёт: точки доступа с EAP шлют всегда, коммутатор с PAP для входа администраторов — не обязательно.

Два предупреждения о секретах. -SharedSecret — обычная строка, и Get-NpsRadiusClient без Select-Object/Format-Table выводит секрет каждого клиента открытым текстом, как и Get-NpsSharedSecretTemplate; в общие логи и на экраны это выводить нельзя. Второе: шаблоны секретов (один секрет на группу однотипных устройств, чтобы менять его в одном месте) создаются только в консоли, модуль умеет их читать, но не создавать и не назначать клиенту:

PS C:\> Get-NpsSharedSecretTemplate | Select-Object Name

Name
----
default secret
wifi
vpn

VendorName — для условий политик по производителю (список — netsh nps show vendors). Адрес может быть подсетью (192.168.1.0/24) для группы устройств с одним секретом — удобно и небезопасно: любая машина подсети становится клиентом RADIUS. Секрет — это всё, что отличает настоящий NAS от любого другого устройства с тем же адресом: длинный, случайный, разный для разных групп устройств.


Политики

Запрос проходит две очереди политик, каждая — упорядоченный список, где побеждает первая подходящая.

Политики запросов на подключение (connection request policies) решают, где аутентифицировать: здесь или переслать другому серверу RADIUS (прокси). Условия — тип NAS, адрес клиента, Called-Station-Id, время, имя пользователя с realm. Политика по умолчанию «Use Windows authentication for all users» с условием «любой день, любое время» ловит всё и аутентифицирует локально (Auth-Provider-Type = 1); её хватает, пока не нужен прокси. Запрос, не подошедший ни под одну политику запросов, получает отказ. Здесь же — правила замены для User-Name, Called-Station-Id и Calling-Station-Id: например, отрезать @example.com от имени перед поиском в каталоге.

Сетевые политики (network policies) решают, пускать ли и с чем. У каждой четыре части:

Часть Что
Условия что должно совпасть, чтобы политика применилась: группы Windows (пользователя или компьютера), тип порта NAS (NAS-Port-Type: 19 — Wireless-802.11, 15 — Ethernet, 5 — Virtual для VPN), Called-Station-Id (регулярное выражение по SSID), Calling-Station-Id, адрес и имя клиента RADIUS, день и время, тип туннеля
Разрешение Grant или Deny, и флаг «игнорировать свойства Dial-in учётной записи»
Ограничения методы аутентификации (типы EAP, MS-CHAPv2, PAP…), таймауты, тип порта, время; несовпадение ограничения — отказ, а не переход к следующей политике
Параметры что вернуть в Access-Accept: атрибуты RADIUS стандартные и производителя — VLAN (Tunnel-Type = VLAN, Tunnel-Medium-Type = 802, Tunnel-Pvt-Group-ID = 20, RFC 2868 и 3580), Filter-Id, Session-Timeout, для Cisco shell:priv-lvl=15

Порядок для каждого запроса: условия первой политики совпали → проверить ограничения (метод, тип порта, время) → проверить учётные данные → проверить ограничения учётной записи (отключена, истекла, часы входа, свойство «Network Access Permission» на вкладке Dial-in, если политика не велит его игнорировать) → выдать Accept с параметрами или Reject. Условия не совпали — следующая политика. Ни одна не совпала — Reject с кодом 48 «no matching policy».

Так выглядят политики, которые создаёт мастер NPS для Wi-Fi и VPN, если прочитать их через netsh:

PS C:\> netsh nps show np
Network policy configuration:
---------------------------------------------------------
Name             = Connections to other access servers
State            = Enabled
Processing order = 3
Policy source    = 0

Condition attributes:

Name                                    Id          Value
---------------------------------------------------------
Condition0                              0x1006      "0 00:00-24:00; 1 00:00-24:00; 2 00:00-24:00; 3 00:00-24:00; 4 00:00-24:00; 5 00:00-24:00; 6 00:00-24:00"

Profile attributes:

Name                                    Id          Value
---------------------------------------------------------
NP-Allow-Dial-in                        0x100f      "FALSE"
NP-Authentication-Type                  0x1009      "0x3" "0x4" "0x9" "0xa"
Framed-Protocol                         0x7         "0x1"
Service-Type                            0x6         "0x2"

Network policy configuration:
---------------------------------------------------------
Name             = Virtual Private Network (VPN) Connections
State            = Enabled
Processing order = 2
Policy source    = 0

Condition attributes:

Name                                    Id          Value
---------------------------------------------------------
Condition0                              0x3d        "^5$"
Condition1                              0x1023      "S-1-5-21-1004336348-1177238915-682003330-513"

Profile attributes:

Name                                    Id          Value
---------------------------------------------------------
Ignore-User-Dialin-Properties           0x1005      "TRUE"
NP-Allow-Dial-in                        0x100f      "TRUE"
NP-Allowed-EAP-Type                     0x100a      "1A000000000000000000000000000000"
NP-Authentication-Type                  0x1009      "0x5"
Framed-Protocol                         0x7         "0x1"
Service-Type                            0x6         "0x2"
MS-Link-Utilization-Threshold           0xffffffaa  "0x32"
MS-Link-Drop-Time-Limit                 0xffffffa9  "0x78"
MS-MPPE-Encryption-Policy               0xffffffa7  "0x2"
MS-MPPE-Encryption-Types                0xffffffa6  "0x4"

Network policy configuration:
---------------------------------------------------------
Name             = Secure Wireless Connections
State            = Enabled
Processing order = 1
Policy source    = 0

Condition attributes:

Name                                    Id          Value
---------------------------------------------------------
Condition0                              0x3d        "^18$|^19$"
Condition1                              0x1023      "S-1-5-21-1004336348-1177238915-682003330-513"

Profile attributes:

Name                                    Id          Value
---------------------------------------------------------
EAP-Configuration                       0x1fa2      "19000000000000000000000000000000380000000200000038000000010000001400000043F1B8A07C2D94E6A5B0C7D18E9F2A3B4C5D6E7F0100000001000000100000001A00000000000000"
Ignore-User-Dialin-Properties           0x1005      "TRUE"
NP-Allow-Dial-in                        0x100f      "TRUE"
NP-Allowed-EAP-Type                     0x100a      "1A000000000000000000000000000000" "19000000000000000000000000000000"
NP-Authentication-Type                  0x1009      "0x5" "0x3" "0x9" "0x4" "0xa"
Framed-Protocol                         0x7         "0x1"
Service-Type                            0x6         "0x2"

Ok.

Как это читать. Условия и профиль хранятся как атрибуты с числовыми идентификаторами (полный список — netsh nps show npconditionattributes и show npprofileattributes). 0x3d — NAS-Port-Type регулярным выражением: 18 и 19 — беспроводные типы, 5 — Virtual. 0x1023 — Windows-Groups, и значение — SID группы, а не имя; здесь RID 513, Domain Users, то есть политика для пользователей, и компьютер, который аутентифицируется своей учётной записью (он в Domain Computers, RID 515), под неё не подойдёт. Ограничения и параметры лежат вместе в профиле: NP-Allow-Dial-in — разрешение (Grant/Deny), 0x1005 — игнорировать Dial-in, NP-Authentication-Type — разрешённые методы (1 — PAP, 3 — MS-CHAP, 4 — MS-CHAPv2, 5 — EAP, 9 и 0xa — MS-CHAP и MS-CHAPv2 со сменой пароля), NP-Allowed-EAP-Type — типы EAP: первый байт — номер типа, 0x19 = 25 — PEAP, 0x1A = 26 — EAP-MSCHAPv2. В EAP-Configuration — настройки PEAP, и среди байтов виден 20-байтовый отпечаток сертификата сервера (43F1B8A0…). Последней стоит запрещающая политика по умолчанию «Connections to other access servers» с условием «любое время»: запрос, не подошедший под рабочие политики, получает от неё отказ с кодом 65, а не 48.

Создать такую политику из командной строки можно одной командой netsh nps add np с парами conditionid/conditiondata и profileid/profiledata. Пример — вход администраторов на коммутаторы через RADIUS: коммутатор спрашивает пароль, присылает его PAP внутри RADIUS и получает уровень привилегий:

PS C:\> $sid = (Get-ADGroup 'Network Admins').SID.Value
PS C:\> netsh nps add np name="Switch admins" state="enable" processingorder="1" policysource="0" conditionid="0x1023" conditiondata="$sid" conditionid="0x100c" conditiondata="192.168.1.2" profileid="0x100f" profiledata="TRUE" profileid="0x1005" profiledata="TRUE" profileid="0x1009" profiledata="0x1" profileid="0x6" profiledata="0x6" profileid="0x1388" profiledata="shell:priv-lvl=15"

0x100c — Client-IP-Address, адрес клиента RADIUS; 0x6 со значением 6 — Service-Type = Administrative-User; 0x1388 — Cisco-AV-Pair, атрибут Cisco внутри Vendor-Specific. PAP (Password Authentication Protocol, RFC 1334) — пароль как есть, в RADIUS он закрыт только секретом, поэтому такой клиент обязательно с requireauthattrib. Рабочий способ для сложных политик — собрать первую в консоли и дальше держать конфигурацию файлом:

PS C:\> Export-NpsConfiguration -Path C:\NPS\nps-config.xml

Файл содержит секреты клиентов и удалённых серверов открытым текстом — хранится как пароль. Он же — способ держать два сервера NPS одинаковыми: Import-NpsConfiguration -Path на втором, а NAS настраивают на оба с одинаковым секретом. Настройки записи в SQL Server в экспорт не попадают, а отпечаток сертификата в EAP-Configuration указывает на сертификат первого сервера — на втором его нужно выбрать заново.


EAP и сертификат сервера

Для Wi-Fi и проводного 802.1X ограничение «методы аутентификации» в политике — это тип EAP, и выбор между ними определяет, что доказывает клиент:

Метод Клиент доказывает Сервер доказывает Где применяется
PEAP с EAP-MSCHAPv2 имя и пароль домена внутри TLS-туннеля сертификат сервера Wi-Fi и 802.1X с паролем: Windows, macOS, iOS, Android
EAP-TLS сертификат клиента (компьютера или пользователя) сертификат сервера Wi-Fi и 802.1X без паролей: нужен выпущенный клиенту сертификат из части 25
PEAP с EAP-TLS сертификат клиента внутри туннеля сертификат сервера то же, с защитой идентификатора
EAP-MSCHAPv2 без PEAP имя и пароль по схеме вызов-ответ ответом на вызов клиента VPN IKEv2, где туннель уже даёт IPsec (часть 28)
MS-CHAPv2 без EAP имя и пароль по схеме вызов-ответ ответом на вызов клиента старые VPN и оборудование без EAP
PAP пароль открытым текстом внутри RADIUS ничего вход администраторов на оборудование, где другого нет

PEAP (Protected EAP, спецификация Microsoft MS-PEAP, тип 25) — сначала TLS-туннель, в котором сервер предъявляет сертификат, затем внутри него второй, «внутренний» EAP-метод. EAP-TLS (RFC 5216, тип 13) — взаимная аутентификация TLS: сертификаты предъявляют обе стороны. MS-CHAPv2 (RFC 2759) — вызов-ответ: сервер шлёт случайный вызов, клиент отвечает значением, вычисленным из вызова и NT-хеша пароля, и сам проверяет ответ сервера; EAP-MSCHAPv2 (тип 26) — тот же обмен, завёрнутый в EAP. Чего в NPS нет: EAP-TTLS (RFC 5281, туннель TLS с любым внутренним методом, хоть PAP) и TEAP (туннель с проверкой компьютера и пользователя в одном сеансе) Windows поддерживает только как клиент — для чужих серверов RADIUS.

Два следствия. Первое: во всех методах с туннелем сервер предъявляет сертификат, и клиент обязан его проверять — иначе любой с точкой доступа с тем же SSID соберёт ответы MSCHAPv2 пользователей (атака «злой двойник»). Сертификат — с назначением Server Authentication (OID 1.3.6.1.5.5.7.3.1), с непустым именем субъекта и DNS-именем сервера в SAN, от центра, которому клиенты доверяют. В AD CS для этого есть шаблон RAS and IAS Server (RASAndIASServer): назначения Server и Client Authentication, имя и DNS-имя из каталога, право Enroll — у группы RAS and IAS Servers. Права Autoenroll у группы по умолчанию нет, и на центре шаблон по умолчанию не опубликован: либо опубликовать и выдать Autoenroll, либо запросить вручную — Get-Certificate -Template RASAndIASServer -CertStoreLocation Cert:\LocalMachine\My. Сертификат от своего центра подходит машинам домена, которые доверяют корню по групповой политике; телефоны и гостевые устройства ему не доверяют, поэтому для них иногда берут сертификат публичного центра — и тогда проверка имени сервера в профиле клиента обязательна, ведь сертификат того же публичного центра купить может любой. На клиентах — профиль, где указаны доверенный корень и имя сервера; как его раздать — в следующей части.

Второе: MS-CHAPv2 по сути — NTLM. NTLM — схема вызов-ответ на NT-хеше пароля (часть 3): NPS сам пароля не знает и передаёт вызов и ответ контроллеру по Netlogon, как любой сервер, проверяющий NTLM. Учётные записи из группы Protected Users (часть 15) по NTLM не аутентифицируются, так что войти через PEAP-MSCHAPv2 они не смогут, и для них остаётся EAP-TLS.

Какой сертификат предъявляет сервер, задаётся в свойствах типа EAP в политике (в консоли) и хранится в политике отпечатком — тем самым, что виден в EAP-Configuration. NPS предлагает на выбор только сертификаты из хранилища компьютера с назначением Server Authentication и непустым субъектом; после перевыпуска сертификата отпечаток меняется, и в политике нужно выбрать новый.

Чем NPS проверяет учётные данные: для компьютера — учётная запись CORP\WS1$ (клиент называет себя host/ws1.corp.example.com), для пользователя — его имя; по EAP-TLS — сертификат сопоставляется с учётной записью: у пользователя по UPN в SAN, у компьютера по DNS-имени. Центр предприятия с обновлений мая 2022 года добавляет в сертификаты ещё и расширение с SID владельца (OID 1.3.6.1.4.1.311.25.2), по которому контроллеры проверяют, что сертификат выдан именно этой учётной записи. Когда нужно и то, и другое — «аутентификация компьютера при загрузке, пользователя при входе» — в политиках будет две записи, по группе компьютеров и по группе пользователей.


Прокси

NPS умеет не отвечать сам, а пересылать запросы другому серверу RADIUS: партнёру из части 22, облачному провайдеру аутентификации, старому серверу во время миграции. Для EAP-TLS и PEAP-TLS между лесами это единственный путь: по документации доверие между лесами здесь не помогает, нужен прокси к NPS второго леса. Командлетов для групп удалённых серверов нет, всё — через netsh nps: группа, сервер в ней и политика запросов, которая направляет в группу по realm в имени:

PS C:\> netsh nps add remoteservergroup name="Partner RADIUS"
PS C:\> netsh nps add remoteserver remoteservergroup="Partner RADIUS" address="radius.partner.example.net" authport="1812" acctport="1813" authsharedsecret="$(Read-Host 'Secret')" acctsharedsecret="$(Read-Host 'Secret')" requireauthattrib="yes" priority="1" weight="50"
PS C:\> netsh nps add crp name="Forward partner realm" state="enable" processingorder="1" policysource="0" conditionid="0x1" conditiondata=".*@partner\.example\.net$" profileid="0x1025" profiledata="0x2" profileid="0x1029" profiledata="Partner RADIUS"

0x1 в политике запросов — User-Name, 0x1025 — Auth-Provider-Type (1 — проверять здесь, 2 — переслать), 0x1029 — имя группы. Запросы с именами *@partner.example.net уходят партнёру, ответы возвращаются NAS как свои. Прокси полезен и внутри организации: один адрес для всех устройств, за которым несколько серверов: в группе сначала используется сервер с приоритетом 1, а между серверами одного приоритета запросы делятся по весу.

На прокси относятся и два флага июльских обновлений 2024 года. requireMsgAuth — отбрасывать ответы удалённых серверов без Message-Authenticator; limitProxyState — отбрасывать запросы, в которых есть атрибут Proxy-State (его добавляет промежуточный прокси), но нет Message-Authenticator. Оба по умолчанию выключены, у каждого есть режим аудита и исключения для отдельных серверов и клиентов:

PS C:\> netsh nps show requiremsgauth

Require Message Auth       = disable
Ok.
PS C:\> netsh nps show limitproxystate

Limit Proxy State           = disable
Ok.

Включаются netsh nps set requiremsgauth all = "enable" и netsh nps set limitproxystate all = "enable" (audit — только писать события 4419 и 4420). Пока они выключены, NPS при каждом запуске службы напоминает о них событием 4421 в журнале System.


Журнал

Три места. Журнал Security — главный: события пишутся по подкатегории аудита Network Policy Server, и на серверах она включена по умолчанию на успех и отказ — проверить можно так:

PS C:\> auditpol /get /subcategory:"Network Policy Server"
System audit policy

Category/Subcategory                      Setting
Logon/Logoff
  Network Policy Server                   Success and Failure
Событие Что
6272 доступ разрешён: пользователь, клиент RADIUS, политики, метод
6273 доступ запрещён, с кодом и текстом причины
6274 запрос отброшен
6275 запрос учёта отброшен
6279, 6280 учётная запись заблокирована и разблокирована механизмом блокировки удалённого доступа NPS

События 6276–6278 — от NAP (Network Access Protection, проверка состояния клиента перед допуском), которой с Windows Server 2016 нет.

Журнал System, источник NPS — состояние самой службы и всё, что связано с клиентами RADIUS:

Событие Что
13 сообщение от адреса, который не зарегистрирован как клиент
14 неверный Authenticator — обычно не совпадает секрет
17 клиент обязан слать Message-Authenticator, а запрос пришёл без него
18 Message-Authenticator неверный — опять секрет
19 запрос с EAP без Message-Authenticator
4400, 4402 соединение LDAP с контроллером установлено; контроллер домена недоступен
4418–4420 отброшено или пропущено в режиме аудита по limitProxyState и requireMsgAuth
4421 requireMsgAuth и/или limitProxyState выключены или в режиме аудита

Коды причин в 6273 (и в поле Reason-Code файла учёта), которые встречаются чаще всего: 16 — неверные учётные данные (пароль, компьютер с устаревшим паролем учётной записи, имя не в том формате); 22 — не удалось договориться о типе EAP (профиль на клиенте не совпадает с политикой); 48 — ни одна сетевая политика не совпала; 49 — не совпала ни одна политика запросов; 65 — доступ запрещён разрешением: Deny в свойствах Dial-in учётной записи или в самой совпавшей политике, как у «Connections to other access servers»; 66 — метод аутентификации не разрешён совпавшей политикой; 8 — учётная запись не найдена; 34, 35, 36, 37 — учётная запись отключена, истекла, заблокирована, вне разрешённых часов входа; 265 — сертификат клиента выпущен центром, которому NPS не доверяет; 258 и 259 — NPS не может проверить отзыв сертификата клиента (недоступен CRL); 268 — сертификат клиента истёк. Если же сертификату сервера не доверяет клиент, он сам обрывает разговор EAP, и причину нужно смотреть на клиенте: NPS видит лишь незавершённый обмен.

Файлы учёта — C:\Windows\System32\LogFiles\IN*.log, по файлу на месяц (IN2610.log — октябрь 2026 года). Формат в консоли выбирается из трёх: DTS Compliant — XML, тот же, что NPS отправляет в SQL Server, и два старых, ODBC и IAS, — строки через запятую. Каждое событие — одна строка <Event>…</Event> с элементами Packet-Type, User-Name, Called-Station-Id, Calling-Station-Id, Client-Friendly-Name, NP-Policy-Name, Authentication-Type, EAP-Friendly-Name, Reason-Code и другими. Настройки можно прочитать через netsh:

PS C:\> netsh nps show filelog

File log configuration:
---------------------------------------------------------
Accounting                     = Enabled
Authentication                 = Enabled
Periodic accounting status     = Enabled
Periodic authentication status = Enabled
Directory                      = C:\Windows\system32\LogFiles
Format                         = ODBC formatting
Delete old logs                = Enabled
Frequency                      = Monthly logs
Max size                       = 10 MB

Ok.

netsh здесь знает только два значения, IAS и ODBC, и формат DTS Compliant показывает как ODBC formatting, хотя файл при этом — XML. Документация предупреждает о важном свойстве файлового журнала: если запись не удаётся (например, кончился диск), NPS перестаёт обрабатывать запросы, поэтому журнал держат на отдельном томе. Запись можно вести и в SQL Server — локальный или удалённый.


Смотрим руками

Файл учёта хорош тем, что в нём каждый пакет: сгруппируем за месяц по типу пакета, политике и коду причины.

PS C:\> Invoke-Command -ComputerName nps1 -ScriptBlock {
    $type = @{ '1'='Access-Request'; '2'='Access-Accept'; '3'='Access-Reject'; '4'='Accounting-Request'; '11'='Access-Challenge' }
    $log = Get-ChildItem C:\Windows\System32\LogFiles\IN*.log | Sort-Object Name | Select-Object -Last 1
    Get-Content $log.FullName | ForEach-Object { $e = ([xml]$_).Event
        [PSCustomObject]@{ Packet = $type[$e.'Packet-Type'.'#text']; Policy = $e.'NP-Policy-Name'.'#text'; Reason = $e.'Reason-Code'.'#text' } }
} | Group-Object Packet, Policy, Reason -NoElement | Sort-Object Count -Descending | Select-Object Count, Name

Count Name
----- ----
 5048 Access-Request, Secure Wireless Connections, 0
 4589 Access-Challenge, Secure Wireless Connections, 0
  459 Access-Accept, Secure Wireless Connections, 0
  102 Access-Request, Virtual Private Network (VPN) Connections, 0
   68 Access-Challenge, Virtual Private Network (VPN) Connections, 0
   34 Access-Accept, Virtual Private Network (VPN) Connections, 0
    3 Access-Reject, Connections to other access servers, 65
    3 Access-Request, Connections to other access servers, 0

Цифры складываются в протокол. Wi-Fi по PEAP: 459 подключений, на каждое ровно 10 Access-Challenge и 11 Access-Request — 22 пакета: идентификация, начало PEAP, TLS-рукопожатие с сертификатом сервера в нескольких фрагментах, затем внутри туннеля MSCHAPv2 и в конце Access-Accept с ключами. VPN с EAP-MSCHAPv2 без туннеля: 34 подключения по 2 Access-Challenge и 3 Access-Request — идентификация, вызов-ответ MSCHAPv2, успех. Три отказа за месяц — запросы, которые не подошли под рабочие политики и дошли до запрещающей, отсюда код 65. Accounting-Request нет вовсе: эти NAS учёт не присылают, хотя сервер готов его писать. Отдельная деталь: в строках файла поле Authentication-Type у подключений по PEAP равно 11, а у первых пакетов разговора — 5 (EAP); в таблице документации значения 11 нет.

Пакеты целиком можно снять на самом NPS встроенным pktmon и открыть в Wireshark: pktmon filter add -p 1812, pktmon start -c, подключиться, pktmon stop и pktmon etl2pcap PktMon.etl. В первом Access-Request будут User-Name, NAS-IP-Address, NAS-Port-Type = Wireless-802.11, Calling-Station-Id, Called-Station-Id с SSID, Message-Authenticator и EAP-Message; пароля нет ни в одном пакете — внутренний обмен MSCHAPv2 зашифрован TLS, и точка доступа пересылает его, не раскрывая.

Событие 6272 об одном из этих подключений:

PS C:\> Invoke-Command -ComputerName nps1 -ScriptBlock { (Get-WinEvent -FilterHashtable @{LogName='Security'; Id=6272} -MaxEvents 1).Message }
Network Policy Server granted access to a user.

User:
	Security ID:			S-1-5-21-1004336348-1177238915-682003330-1105
	Account Name:			CORP\alice
	Account Domain:			CORP
	Fully Qualified Account Name:	CORP\alice

Client Machine:
	Security ID:			S-1-0-0
	Account Name:			-
	Fully Qualified Account Name:	-
	Called Station Identifier:		AA-BB-CC-DD-EE-FF:CorpWiFi
	Calling Station Identifier:		00-11-22-33-44-55

NAS:
	NAS IPv4 Address:		192.168.1.5
	NAS IPv6 Address:		-
	NAS Identifier:			AABBCCDDEEFF
	NAS Port-Type:			Wireless - IEEE 802.11
	NAS Port:			-

RADIUS Client:
	Client Friendly Name:		ap-floor1
	Client IP Address:			192.168.1.5

Authentication Details:
	Connection Request Policy Name:	Secure Wireless Connections
	Network Policy Name:		Secure Wireless Connections
	Authentication Provider:		Windows
	Authentication Server:		nps1.corp.example.com
	Authentication Type:		PEAP
	EAP Type:			Microsoft: Secured password (EAP-MSCHAP v2)
	Account Session Identifier:		43393444463435364332313530323243
	Logging Results:			Accounting information was written to the local log file.

Кто (Account Name — имя, как его ввёл пользователь), с какого устройства (Calling Station Identifier — MAC клиента), через какую точку и SSID, по каким политикам, каким методом. Раздел Client Machine пуст (S-1-0-0 — пустой SID): он заполняется, когда аутентифицируется компьютер. NAS Identifier эта точка доступа заполняет своим MAC без разделителей, а Account Session Identifier — шестнадцатеричная запись строки Acct-Session-Id (4339… — это символы C9…). SID в Security ID не разрешён в имя, потому что сообщение собрано в удалённом сеансе; в Event Viewer на самом сервере там будет имя.

Сводка за сутки — по номерам полей из шаблона события: у 6272 и 6273 политика — поле 17, тип аутентификации — 20, тип EAP — 21, код причины в 6273 — 23. Значения нужно доставать внутри Invoke-Command: после десериализации Properties[n].Value пустые.

PS C:\> Invoke-Command -ComputerName nps1 -ScriptBlock {
    Get-WinEvent -FilterHashtable @{LogName='Security'; Id=6272; StartTime=(Get-Date).AddDays(-1)} |
        ForEach-Object { [PSCustomObject]@{ Policy = $_.Properties[17].Value; Auth = $_.Properties[20].Value; Eap = $_.Properties[21].Value } }
} | Group-Object Policy, Auth, Eap -NoElement | Select-Object Count, Name

Count Name
----- ----
   12 Secure Wireless Connections, PEAP, Microsoft: Secured password (EAP-MSCHAP v2)

Двенадцать — потому что журнал Security перезаписывается быстро: за месяц в файле учёта 459 подключений по Wi-Fi, а журнал Security сервера, на котором снят этот вывод (NPS там стоит на контроллере, и журнал заполняют ещё события Kerberos), хранит меньше суток. Для истории — файл учёта. То же для отказов, сгруппированных по причине и политике, — отчёт, который стоит смотреть утром:

PS C:\> Invoke-Command -ComputerName nps1 -ScriptBlock {
    Get-WinEvent -FilterHashtable @{LogName='Security'; Id=6273; StartTime=(Get-Date).AddDays(-1)} |
        ForEach-Object { [PSCustomObject]@{ Reason = $_.Properties[23].Value; Policy = $_.Properties[17].Value } }
} | Group-Object Reason, Policy -NoElement | Select-Object Count, Name
Get-WinEvent: No events were found that match the specified selection criteria.

Отказов за сутки не было, и Get-WinEvent сообщает об этом ошибкой; в скрипте отчёта к нему стоит добавить -ErrorAction SilentlyContinue. Если отказы есть, имя пользователя — поле 3 (DOMAIN\user): сорок отказов по коду 16 от одной служебной учётной записи — это устройство со старым паролем, код 22 у одного пользователя — профиль Wi-Fi на его машине настроен на другой тип EAP.

Что сервер знает о себе — порты:

PS C:\> netsh nps show ports

Ports configuration:
---------------------------------------------------------
Accounting ports     = 1813,1646
Authentication ports = 1812,1645

Ok.

и напоминание о Blast-RADIUS в журнале System при каждом запуске службы:

PS C:\> Invoke-Command -ComputerName nps1 -ScriptBlock { (Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='NPS'; Id=4421} -MaxEvents 1).Message }
RequireMsgAuth and/or limitProxyState configuration is in Disable mode. These settings should be configured in Enable mode for security purposes. See https://support.microsoft.com/help/5040268 to learn more.

И проверка, что RADIUS вообще отвечает, с машины без NAS под рукой: UDP не проверить Test-NetConnection, но RADIUS-клиент для командной строки (radclient из FreeRADIUS на Linux) с зарегистрированным адресом и секретом отправит Access-Request с PAP и покажет Accept или Reject — и соответствующее событие в журнале. Для этого заводят отдельную тестовую учётную запись: неверный пароль в таких проверках считается неудачным входом и приближает блокировку.


Источники

Протокол RADIUS:

  • RFC 2865 — RADIUS: пакеты, коды, Authenticator, сокрытие User-Password, атрибуты и порт 1812;
  • RFC 2866 — учёт: Accounting-Request и Accounting-Response, Start, Interim-Update, Stop, порт 1813;
  • RFC 2869 — расширения RADIUS, атрибут Message-Authenticator (HMAC-MD5);
  • RFC 2868 и RFC 3580 — атрибуты туннеля и их использование с 802.1X: VLAN через Tunnel-Type, Tunnel-Medium-Type, Tunnel-Pvt-Group-ID;
  • RFC 2548 — атрибуты Microsoft внутри Vendor-Specific, MS-MPPE-Send-Key и MS-MPPE-Recv-Key;
  • RFC 6614 — RADIUS поверх TLS (RadSec);
  • KB5040268 — Blast-RADIUS (CVE-2024-3596) в NPS: requireauthattrib, limitProxyState, requireMsgAuth, умолчания и события 4418–4421.

EAP и методы аутентификации:

Network Policy Server:

Журналы:

Связь с каталогом:

  • Protected Users Security Group — запрет NTLM для членов группы;
  • KB5014754 — расширение с SID в сертификатах и строгое сопоставление сертификатов на контроллерах.

NPS готов отвечать; точки доступа зарегистрированы как клиенты; сертификат сервера выдан. Осталось научить рабочие станции спрашивать разрешения, прежде чем выходить в эфир.

Дальше — часть 27: Wi-Fi по 802.1X. WPA2-Enterprise и WPA3-Enterprise и чем они отличаются от домашнего пароля; роли supplicant, authenticator и сервера аутентификации; настройка точки доступа как клиента RADIUS; профиль Wi-Fi для машин домена через групповую политику — с проверкой сертификата сервера, аутентификацией компьютера при загрузке и пользователя при входе; политики NPS для Wi-Fi с VLAN; и как это выглядит с телефона, который в домене не состоит.

Оставить комментарий могут только зарегистрированные пользователи.

Войдите на сайт или зарегистрируйтесь, чтобы оставить комментарий.