Windows Server для самых маленьких. Часть 27: Подключаем Wi-Fi по 802.1X

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

Радио, кадры 802.11, ассоциация и четырёхстороннее рукопожатие WPA2 разобраны в части 3 сетевой серии. Там же был общий пароль сети — PSK, из которого все клиенты выводят ключи. В офисе общий пароль не работает: его знает каждый бывший сотрудник, его нельзя отозвать для одного человека, и он ничего не говорит о том, кто подключился. Замена — 802.1X: подключение к сети требует аутентификации в каталоге, у каждого клиента свои ключи, и доступ отзывается отключением учётной записи. Сервер RADIUS из прошлой части уже готов; теперь — точка доступа, клиент и политики.


Personal и Enterprise

У WPA2 и WPA3 два режима, и разница между ними — в том, откуда берётся PMK, главный ключ сеанса, с которого начинается рукопожатие:

Personal Enterprise
Откуда PMK из общего пароля (WPA2: PBKDF2 от PSK и SSID; WPA3: обмен SAE) из EAP: сервер RADIUS присылает точке в MS-MPPE-Recv-Key после успешной аутентификации
Кто подключается любой, кто знает пароль учётная запись каталога или владелец сертификата
Отзыв сменить пароль у всех отключить учётную запись
Ключи у всех выведены из одного секрета у каждого сеанса свои, никто не знает чужих
Что знает точка ничего о пользователе имя, группу, VLAN из ответа RADIUS

PBKDF2 — функция, которая многократным хешированием растягивает пароль в ключ; при WPA2-Personal любой, кто записал рукопожатие, может перебирать пароли у себя. SAE (Simultaneous Authentication of Equals) в WPA3-Personal — обмен, в котором обе стороны доказывают знание пароля, не передавая ничего, по чему его можно перебирать без связи с точкой. В Enterprise пароля сети нет вовсе: PMK — результат аутентификации конкретного клиента.

WPA3-Enterprise — тот же 802.1X с двумя добавлениями: обязательная защита управляющих кадров (PMF, 802.11w: кадры отключения подписаны, и поддельным deauth клиента не выбить) и необязательный режим 192 бит с фиксированным набором стойких алгоритмов, в котором из методов EAP разрешён только EAP-TLS. В Windows оба режима есть с Windows 10 2004 и Windows Server 2022, а в профиле WPA3-Enterprise стал отдельным значением (WPA3ENT) в Windows 11. Переходный режим WPA2/WPA3 на одном SSID позволяет старым клиентам подключаться по WPA2-Enterprise, новым — по WPA3. Для домена из современных Windows и телефонов подходит WPA3-Enterprise, для парка с принтерами и старыми устройствами — переходный режим.


Три роли

 Supplicant               Authenticator                 Authentication server
 (клиент, ws1)            (точка доступа)               (nps1, RADIUS)
    │                         │                               │
    │ ─ ассоциация 802.11 ───►│  порт закрыт: пропускает      │
    │                         │  только EAPOL                 │
    │ ─ EAPOL-Start ─────────►│                               │
    │◄─ EAP-Request/Identity ─┤                               │
    │ ─ EAP-Response/Identity►│ ─ Access-Request ────────────►│
    │◄─ EAP-Request (PEAP) ───┤◄─ Access-Challenge ───────────┤
    │ ─ EAP-Response ────────►│ ─ Access-Request ────────────►│   TLS, внутри MSCHAPv2
    │        … ещё десяток …  │        … пересылка …          │   или сертификат
    │◄─ EAP-Success ──────────┤◄─ Access-Accept + PMK + VLAN ─┤
    │                         │  порт открыт для этого MAC    │
    │◄─ EAPOL-Key 1/4 ────────┤  четырёхстороннее рукопожатие │
    │ ─ EAPOL-Key 2/4 ───────►│  из PMK: PTK и GTK            │
    │◄─ EAPOL-Key 3/4 ────────┤                               │
    │ ─ EAPOL-Key 4/4 ───────►│                               │
    │ ─ DHCP Discover ───────►│  обычный трафик               │

Supplicant — клиент: в Windows это служба WLAN AutoConfig (wlansvc) для беспроводных сетей и Wired AutoConfig (dot3svc) для проводных. Authenticator — точка доступа или коммутатор: держит порт закрытым, пропуская только кадры EAPOL (EAP over LAN, EtherType 0x888E), переупаковывает EAP между клиентом и RADIUS и открывает порт по Access-Accept. Сервер аутентификации — NPS. Точка не понимает содержимого EAP, не видит пароля и не принимает решений: она исполняет ответ сервера, включая номер VLAN, если он там есть. Внутри EAP для паролей домена едет PEAP: TLS-туннель, в котором сервер предъявляет сертификат, а в туннеле — EAP-MSCHAPv2, вызов-ответ на NT-хеше пароля; для сертификатов — EAP-TLS, где сертификаты предъявляют обе стороны (оба метода разобраны в прошлой части).


Точка доступа

На стороне точки (или контроллера точек) четыре настройки, одинаковые у любого производителя: SSID CorpWiFi, безопасность WPA2/WPA3-Enterprise, сервер RADIUS 192.168.1.30:1812 с тем же секретом, что у клиента RADIUS в NPS (в прошлой части — шаблон wifi), и второй сервер, если NPS два. Учёт на 1813 включают, если нужен: без него NPS видит только аутентификацию, и Accounting-Request в файле учёта не будет, как у точек в прошлой части. Пятая настройка, если нужны VLAN по пользователю, — «динамическое назначение VLAN по RADIUS» (у разных производителей называется по-разному). Точка при этом помечает трафик клиента меткой 802.1Q того VLAN, который пришёл в Access-Accept атрибутами Tunnel-Type = VLAN (13), Tunnel-Medium-Type = IEEE-802 (6), Tunnel-Private-Group-ID = 20, а порт точки на коммутаторе — транк с нужными VLAN. Обычно там же выбирается, что делать с клиентом, для которого сервер VLAN не прислал: оставить в сети SSID или отказать.

В каждом запросе точка присылает Called-Station-Id вида AA-BB-CC-1E-00-01:CorpWiFi — BSSID радиомодуля, через который подключился клиент, и SSID (формат из RFC 3580). У точки с двумя диапазонами BSSID два, и в журнале NPS одна точка видна под двумя значениями. По SSID в этом атрибуте NPS отличит запросы с CorpWiFi от запросов с гостевого CorpGuest на той же точке, и это условие стоит ставить в каждую политику.


Профиль на клиенте

Профиль беспроводной сети — XML, и всё, что в нём важно, находится в блоке OneX → EAPConfig. Собрать его можно на одной машине через интерфейс и выгрузить (netsh wlan export profile name="CorpWiFi" folder=C:\Temp), или написать по образцу из документации:

<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
  <name>CorpWiFi</name>
  <SSIDConfig><SSID><name>CorpWiFi</name></SSID></SSIDConfig>
  <connectionType>ESS</connectionType>
  <connectionMode>auto</connectionMode>
  <MSM>
    <security>
      <authEncryption>
        <authentication>WPA3ENT</authentication>
        <encryption>AES</encryption>
        <useOneX>true</useOneX>
      </authEncryption>
      <PMKCacheMode>enabled</PMKCacheMode>
      <OneX xmlns="http://www.microsoft.com/networking/OneX/v1">
        <authMode>machineOrUser</authMode>
        <EAPConfig>
          <EapHostConfig xmlns="http://www.microsoft.com/provisioning/EapHostConfig">
            <EapMethod>
              <Type xmlns="http://www.microsoft.com/provisioning/EapCommon">25</Type>
              <AuthorId xmlns="http://www.microsoft.com/provisioning/EapCommon">0</AuthorId>
            </EapMethod>
            <Config xmlns="http://www.microsoft.com/provisioning/EapHostConfig">
              <Eap xmlns="http://www.microsoft.com/provisioning/BaseEapConnectionPropertiesV1">
                <Type>25</Type>
                <EapType xmlns="http://www.microsoft.com/provisioning/MsPeapConnectionPropertiesV1">
                  <ServerValidation>
                    <DisableUserPromptForServerValidation>true</DisableUserPromptForServerValidation>
                    <ServerNames>nps1.corp.example.com</ServerNames>
                    <TrustedRootCA>3f 1a 2b 3c 4d 5e 6f 70 81 92 a3 b4 c5 d6 e7 f8 09 1a 2b 3c</TrustedRootCA>
                  </ServerValidation>
                  <FastReconnect>true</FastReconnect>
                  <InnerEapOptional>false</InnerEapOptional>
                  <Eap xmlns="http://www.microsoft.com/provisioning/BaseEapConnectionPropertiesV1">
                    <Type>26</Type>
                    <EapType xmlns="http://www.microsoft.com/provisioning/MsChapV2ConnectionPropertiesV1">
                      <UseWinLogonCredentials>true</UseWinLogonCredentials>
                    </EapType>
                  </Eap>
                  <EnableQuarantineChecks>false</EnableQuarantineChecks>
                  <RequireCryptoBinding>true</RequireCryptoBinding>
                </EapType>
              </Eap>
            </Config>
          </EapHostConfig>
        </EAPConfig>
      </OneX>
    </security>
  </MSM>
</WLANProfile>

Что здесь решает безопасность и поведение:

  • authMode = machineOrUser — компьютер аутентифицируется своей учётной записью (host/ws1.corp.example.com, в каталоге CORP\WS1$), пока никто не вошёл, пользователь — своей после входа; сеть доступна до входа, и политики, сценарии, смена пароля работают как на проводе. Это значение по умолчанию: если authMode в профиле нет, Windows ведёт себя так же. Отсюда следствие, которое видно в «Смотрим руками»: без политики NPS для компьютеров каждая попытка до входа получает отказ.
  • Type 25 — PEAP; внутри Type 26 — EAP-MSCHAPv2 с учётными данными входа в Windows (UseWinLogonCredentials), пароль никто не вводит.
  • ServerValidation: отпечаток корневого сертификата из части 25 (байты через пробел; здесь условный) и имя сервера. Имя сравнивается с субъектом сертификата сервера точно, а регулярным выражением — если в строке есть хотя бы одна * (nps.*\.corp\.example\.com); несколько имён — через ;. Без ServerNames клиент примет сертификат с любым именем от любого доверенного корня, без TrustedRootCA — от любого корня из своего хранилища. DisableUserPromptForServerValidation = true — не спрашивать пользователя «доверять ли», а просто отказывать.
  • RequireCryptoBinding — требовать от сервера cryptobinding TLV, которым PEAP связывает внутреннюю аутентификацию с внешним TLS-туннелем: ответ MSCHAPv2, перехваченный в одном туннеле, нельзя переслать в другой.
  • FastReconnect — быстрое переподключение PEAP: клиент возобновляет прежний TLS-сеанс вместо полного рукопожатия, и сервер не спрашивает пароль заново. PMKCacheMode — кеш PMK на клиенте: при возврате к точке, с которой клиент уже аутентифицировался, рукопожатие начинается с сохранённого PMK, и до RADIUS дело не доходит вовсе.

Установка профиля на машину и проверка:

PS C:\> netsh wlan add profile filename=C:\Temp\CorpWiFi.xml user=all
PS C:\> netsh wlan show profiles

user=all — профиль для всех пользователей машины (это и умолчание), без interface= — на все беспроводные адаптеры. Служба wlansvc должна работать: на машине без беспроводного адаптера она остановлена, и любая команда netsh wlan отвечает одной строкой:

PS C:\> netsh wlan show profiles
The Wireless AutoConfig Service (wlansvc) is not running.

Централизованно — групповой политикой: Computer Configuration → Policies → Windows Settings → Security Settings → Wireless Network (IEEE 802.11) Policies, где создаётся политика с тем же профилем, теми же вкладками PEAP и той же проверкой сертификата. Хранится она в контейнере объекта групповой политики в каталоге (CN=IEEE80211,CN=Windows,CN=Microsoft,CN=Machine,…) объектом класса ms-net-ieee-80211-GroupPolicy, где весь XML лежит в атрибуте ms-net-ieee-80211-GP-PolicyData; проводные политики — классом ms-net-ieee-8023-GroupPolicy, а класс msieee80211-Policy в схеме остался от двоичного формата политик Windows XP. Применяет её расширение политики беспроводных сетей; командлетов для неё нет, только консоль. Второй централизованный путь — положить XML в SYSVOL и выполнить netsh wlan add profile сценарием запуска или задачей планировщика из предпочтений; он уступает первому в том, что не удаляет профиль при отмене политики. Для сертификата сервера, выданного публичным центром (о чём ниже), TrustedRootCA — отпечаток публичного корня, он есть на всех машинах.


Политики NPS

Две сетевые политики, обе с условием по типу порта и SSID: одна для компьютеров, одна для пользователей. В консоли NPS → Network Policies → New; в экспорте конфигурации — два блока. Что в них:

Wi-Fi — Domain Computers Wi-Fi — Domain Users
Условия Windows Groups: CORP\Domain Computers; NAS Port Type: Wireless — IEEE 802.11; Called Station ID: .*:CorpWiFi$ Windows Groups: CORP\Domain Users; остальное то же
Разрешение Grant Grant
Ограничения: методы EAP: Microsoft: Protected EAP (PEAP) с внутренним EAP-MSCHAP v2; сертификат сервера nps1.corp.example.com; остальные методы сняты то же
Параметры: атрибуты Tunnel-Type = VLAN, Tunnel-Medium-Type = 802, Tunnel-Pvt-Group-ID = 20; Session-Timeout = 28800 VLAN 20 или свой по группе
Параметры: учётная запись «Ignore user account dial-in properties» включено включено

Session-Timeout в ответе на 802.1X — срок, через который точка заново аутентифицирует клиента (если вместе с ним прислан Termination-Action = RADIUS-Request) или отключает его (RFC 3580). Порядок политик — компьютеры первыми, затем пользователи. VLAN по группам делается третьей и четвёртой политикой выше по списку с условием по более узкой группе и другим Tunnel-Pvt-Group-ID: инженеры в VLAN 30, остальные в 20. Для этого на точках должны быть транки, а у DHCP (часть 8) — области для каждого VLAN с ретрансляцией.

Мастер NPS для беспроводных подключений, как в прошлой части, создаёт одну политику «Secure Wireless Connections» — для групп, которые ему указали (там — Domain Users), без условия по SSID и без VLAN. Компьютеры под неё не подходят, и их запросы доходят до запрещающей политики по умолчанию.

Для EAP-TLS, где у клиентов есть сертификаты по шаблону Corp Computer из части 25, ограничение «методы» — Smart Card or other certificate, и пароля в обмене нет вовсе: это предпочтительный вариант для компьютеров домена, PEAP остаётся для пользователей без сертификатов и для устройств не из домена.


Устройства не из домена

Телефоны, ноутбуки подрядчиков, личные устройства. Три подхода, от простого к правильному.

Отдельный SSID с паролем — CorpGuest с WPA3-Personal, в гостевом VLAN без доступа внутрь. Не решает задачу доступа к ресурсам, но снимает вопрос для половины устройств.

PEAP с именем и паролем домена. Работает на всём, но клиент должен проверять сертификат сервера, а для этого ему нужен наш корневой сертификат. Android после обновлений 11-й версии не позволяет выбрать «не проверять» и требует указать центр и домен сервера; iOS спрашивает «доверять?» при первом подключении, и пользователь нажмёт «да» любому. Корень распространяют через MDM (систему управления мобильными устройствами) или через профиль конфигурации, либо — часто правильнее — выдают NPS сертификат публичного центра на имя в своём публичном домене, например wifi.example.com: тогда устройства доверяют ему из коробки, и в профиле остаётся указать это имя. Разрешаться в DNS оно не обязано: клиент к нему не подключается, а только сравнивает с сертификатом. Учётная запись в PEAP — alice@corp.example.com или CORP\alice; MSCHAPv2 означает, что это не для членов Protected Users.

EAP-TLS с сертификатом пользователя — MDM (Intune и аналоги) выдаёт сертификат по шаблону через SCEP или коннектор к центру, профиль Wi-Fi приезжает вместе с ним, пароль не вводится и не хранится на устройстве. SCEP (Simple Certificate Enrollment Protocol, RFC 8894) — протокол, по которому устройство само создаёт ключ и отправляет запрос на сертификат по HTTP посреднику центра, предъявив одноразовый пароль от MDM. Для телефонов сотрудников это конечное состояние.


Проводной 802.1X

Коммутатор с dot1x на портах — тот же механизм без радио: порт закрыт до EAP-Success, authenticator — коммутатор, VLAN назначается по ответу RADIUS. Отличия на стороне Windows: служба Wired AutoConfig (dot3svc) по умолчанию остановлена и запускается вручную, и без неё клиент не отвечает на EAP-Request; политика — Wired Network (IEEE 802.3) Policies в той же ветке групповой политики, с тем же PEAP и проверкой сертификата; профиль — netsh lan add profile filename=… (без interface= — профиль машины для всех проводных адаптеров).

PS C:\> Get-Service dot3svc, wlansvc | Select-Object Name, Status, StartType

Name     Status StartType
----     ------ ---------
dot3svc Stopped    Manual
wlansvc Stopped    Manual

PS C:\> netsh lan show interfaces

The Wired AutoConfig Service (dot3svc) is not running.

Так выглядит рабочая станция, где 802.1X ещё не включали (и беспроводного адаптера нет). Включение — Set-Service dot3svc -StartupType Automatic и Start-Service dot3svc или та же настройка службы групповой политикой; после этого netsh lan show interfaces показывает состояние аутентификации на каждом адаптере.

Устройства без supplicant — принтеры, IP-телефоны, камеры — пускают через MAB (MAC Authentication Bypass): коммутатор, не дождавшись EAPOL, отправляет Access-Request, в котором MAC-адрес клиента стоит в User-Name и в Calling-Station-Id, а часто и в User-Password по PAP (пароль открытым текстом, закрытый только секретом RADIUS). В NPS для этого два пути: учётные записи, названные MAC-адресами, в отдельной группе, и сетевая политика с разрешённым PAP и VLAN принтеров; или политика запросов с условием по Calling-Station-Id и настройкой «Accept users without validating credentials» — тогда NPS отвечает Accept, ничего не проверяя. Это не аутентификация (MAC подделывается), а инвентаризация с изоляцией, и так к ней и относятся: такая политика запросов должна ловить только порты для устройств и только их MAC.


Что ломается

Признаки, которые встречаются чаще всего, и где смотреть:

  • Все отвалились разом — истёк сертификат NPS. Клиент, получив сертификат сервера, сам обрывает разговор, и в NPS нет ни отказа, ни 6273 — в файле учёта остаётся Access-Challenge, за которым ничего не последовало. Поэтому за сроком сертификата NPS следят отдельно, а после перевыпуска выбирают новый в каждой политике (отпечаток в EAP-Configuration меняется). Для EAP-TLS то же даёт недоступный CRL центра, который выдал сертификаты клиентам (часть 25): 6273 с кодом 258 или 259.
  • Один клиент не доверяет серверу — не тот корень в TrustedRootCA, имя сертификата не совпало с ServerNames, или NPS после перевыпуска предъявляет другой сертификат. В NPS это тоже не отказ, а обмен, оборвавшийся после Access-Challenge с сертификатом; причина — на клиенте, в событии 12013.
  • Код 22 — тип EAP в профиле не совпадает с политикой: PEAP против EAP-TLS, или внутренний метод.
  • Код 16 у компьютера — пароль учётной записи компьютера рассинхронизирован (откат снимка, часть 18); у пользователя — неверный или устаревший сохранённый пароль.
  • Код 48 — ни одна сетевая политика не подошла: не та группа, не тот SSID в условии, не тот тип порта. Если последней стоит запрещающая политика по умолчанию «Connections to other access servers», тот же случай даёт код 65.
  • Подключается, а сети нет — VLAN: точка не настроена на динамический VLAN, или на транке нет этого VLAN, или в нём нет DHCP.
  • Подключается только после входа — машинной аутентификации нет: authMode стоит user, или в NPS нет политики для Domain Computers, и запросы компьютера получают 65. Политики компьютера при загрузке не применяются.

На клиенте всё это видно в журнале Microsoft-Windows-WLAN-AutoConfig/Operational; коды и тексты событий — из манифеста провайдера:

PS C:\> (Get-WinEvent -ListProvider Microsoft-Windows-WLAN-AutoConfig).Events |
    Where-Object Id -in 8001, 8002, 11005, 11006, 12011, 12012, 12013 |
    Sort-Object Id -Unique | ForEach-Object { '{0,5}  {1}' -f $_.Id, ($_.Description -split "`r?`n")[0] }
 8001  WLAN AutoConfig service has successfully connected to a wireless network.
 8002  WLAN AutoConfig service failed to connect to a wireless network.
11005  Wireless security succeeded.
11006  Wireless security failed.
12011  Wireless 802.1x authentication started.
12012  Wireless 802.1x authentication succeeded.
12013  Wireless 802.1x authentication failed.

Компьютер и пользователь различаются не номером события, а полем Identity в 12012: host/ws1.corp.example.com или имя пользователя. В 12013 — причина и код ошибки EAP, в 8001 — тип аутентификации и шифр подключения, в 8002 — причина неудачи. У проводного 802.1X свой журнал, Microsoft-Windows-Wired-AutoConfig/Operational, с событиями 15503 (аутентификация началась), 15505 (успешно) и 15514 (не удалась). netsh wlan show wlanreport с правами администратора собирает события за последние три дня в HTML-отчёт по сеансам. На сервере — 6272 и 6273 прошлой части и файл учёта.


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

Вывод снят на сервере, где NPS обслуживает три точки доступа с одной политикой «Secure Wireless Connections» из прошлой части; имена точек, SSID и адреса заменены на имена статьи.

Какой сертификат предъявляет сервер — по отпечатку из EAP-Configuration политики:

PS C:\> Invoke-Command -ComputerName nps1 -ScriptBlock {
    $eap = (netsh nps show np | Select-String 'EAP-Configuration' | Select-Object -First 1).Line
    $thumb = [regex]::Match($eap, '14000000([0-9A-F]{40})').Groups[1].Value
    $cert = Get-Item "Cert:\LocalMachine\My\$thumb"
    $chain = [System.Security.Cryptography.X509Certificates.X509Chain]::new()
    $null = $chain.Build($cert)
    [PSCustomObject]@{
        Subject  = $cert.Subject
        DnsNames = $cert.DnsNameList.Unicode -join ', '
        EKU      = $cert.EnhancedKeyUsageList.FriendlyName -join ', '
        Chain    = ($chain.ChainElements | ForEach-Object { ($_.Certificate.Subject -split ', ')[0] }) -join ' → '
        Root     = $chain.ChainElements[$chain.ChainElements.Count - 1].Certificate.Thumbprint
    }
} | Format-List Subject, DnsNames, EKU, Chain, Root

Subject  : CN=wifi.example.com
DnsNames : wifi.example.com
EKU      : Server Authentication
Chain    : CN=wifi.example.com → CN=RapidSSL TLS RSA CA G1 → CN=DigiCert Global Root G2
Root     : DF3C24F9BFD666761B268073FE06D1CC8D4F82A4

Это вариант с публичным центром: в профилях клиентов — ServerNames = wifi.example.com и TrustedRootCA с отпечатком DigiCert Global Root G2 (df 3c 24 f9 …), который есть в хранилище любой Windows. Имени в DNS нет — Resolve-DnsName wifi.example.com отвечает DNS name does not exist., — и для Wi-Fi это не мешает: клиент имя только сравнивает.

Через какие точки и радиомодули идут запросы — Called-Station-Id и NAS-Identifier из файла учёта за месяц:

PS C:\> Invoke-Command -ComputerName nps1 -ScriptBlock {
    $log = Get-ChildItem C:\Windows\System32\LogFiles\IN*.log | Sort-Object Name | Select-Object -Last 1
    Get-Content $log.FullName | ForEach-Object { ([xml]$_).Event } |
        Where-Object { $_.'Packet-Type'.'#text' -eq '1' -and $_.'NAS-Port-Type'.'#text' -eq '19' } |
        ForEach-Object { [PSCustomObject]@{ Client = $_.'Client-Friendly-Name'.'#text'; NasId = $_.'NAS-Identifier'.'#text'; Called = $_.'Called-Station-Id'.'#text' } }
} | Group-Object Client, NasId, Called -NoElement | Sort-Object Name | Select-Object Count, Name

Count Name
----- ----
  110 ap-floor1, aabbcc1d0001, AA-BB-CC-1D-00-01:CorpWiFi
 2057 ap-floor1, aabbcc1e0001, AA-BB-CC-1E-00-01:CorpWiFi
 1370 ap-floor2, aabbcc1e0002, AA-BB-CC-1E-00-02:CorpWiFi
   26 ap-floor3, aabbcc1d0003, AA-BB-CC-1D-00-03:CorpWiFi
 1659 ap-floor3, aabbcc1e0003, AA-BB-CC-1E-00-03:CorpWiFi

NAS-Port-Type 19 — Wireless-802.11. У ap-floor1 и ap-floor3 по два BSSID — два радиомодуля, и эти точки подставляют BSSID и в NAS-Identifier; SSID после двоеточия во всех строках один — его и проверяет условие .*:CorpWiFi$.

Сколько стоит подключение — пакеты каждого разговора, сгруппированные по Acct-Session-Id, и флаг быстрого переподключения PEAP, который NPS пишет в Access-Accept:

PS C:\> Invoke-Command -ComputerName nps1 -ScriptBlock {
    $log = Get-ChildItem C:\Windows\System32\LogFiles\IN*.log | Sort-Object Name | Select-Object -Last 1
    Get-Content $log.FullName | ForEach-Object { ([xml]$_).Event } |
        Where-Object { $_.'NP-Policy-Name'.'#text' -eq 'Secure Wireless Connections' } |
        Group-Object { $_.'Acct-Session-Id'.'#text' } | ForEach-Object {
            $accept = @($_.Group | Where-Object { $_.'Packet-Type'.'#text' -eq '2' })
            if ($accept.Count -eq 1) { [PSCustomObject]@{
                Requests   = @($_.Group | Where-Object { $_.'Packet-Type'.'#text' -eq '1' }).Count
                Challenges = @($_.Group | Where-Object { $_.'Packet-Type'.'#text' -eq '11' }).Count
                FastReconnect = $accept[0].'PEAP-Fast-Roamed-Session'.'#text' } } }
} | Group-Object Requests, Challenges, FastReconnect -NoElement | Sort-Object Count -Descending | Select-Object -First 5 Count, Name

Count Name
----- ----
  283 13, 12, 0
  128 5, 4, 1
    2 25, 24, 0
    1 14, 13, 0
    1 23, 22, 0

Два вида подключений. Полное — 13 Access-Request и 12 Access-Challenge до Access-Accept: идентификация, начало PEAP, TLS-рукопожатие, в котором цепочка сертификатов (около 2,8 КБ) при Framed-MTU 1002 уходит несколькими фрагментами и каждый клиент подтверждает пустым ответом, затем внутри туннеля MSCHAPv2 и cryptobinding. Быстрое переподключение (PEAP-Fast-Roamed-Session = 1) — 5 и 4: TLS-сеанс возобновлён, сертификат и MSCHAPv2 не повторяются. Почти треть подключений за месяц прошла так — это работа FastReconnect в профиле. В редких длинных строках (24 и 22 Challenge) под одним Acct-Session-Id уместились два обмена: первый оборвался, второй закончился Accept.

И почему в политиках нужен компьютер. На этом сервере политики для Domain Computers нет, а ноутбуки с профилем по умолчанию (machineOrUser) до входа пользователя аутентифицируются учётной записью компьютера:

PS C:\> Invoke-Command -ComputerName nps1 -ScriptBlock {
    $log = Get-ChildItem C:\Windows\System32\LogFiles\IN*.log | Sort-Object Name | Select-Object -Last 1
    Get-Content $log.FullName | ForEach-Object { ([xml]$_).Event } |
        Where-Object { $_.'SAM-Account-Name'.'#text' -like '*$' } |
        ForEach-Object { [PSCustomObject]@{
            Time    = $_.Timestamp.'#text'
            Packet  = $_.'Packet-Type'.'#text'
            User    = $_.'User-Name'.'#text'
            Account = $_.'SAM-Account-Name'.'#text'
            Policy  = $_.'NP-Policy-Name'.'#text'
            Reason  = $_.'Reason-Code'.'#text' } }
} | Select-Object -First 2 | Format-Table Time, Packet, User, Account, Policy, Reason

Time                    Packet User                       Account    Policy                              Reason
----                    ------ ----                       -------    ------                              ------
10/21/2026 17:39:50.585 1      host/lap1.corp.example.com CORP\LAP1$ Connections to other access servers 0
10/21/2026 17:39:50.585 3                                 CORP\LAP1$ Connections to other access servers 65

Клиент назвал себя host/lap1.corp.example.com, NPS нашёл учётную запись CORP\LAP1$, но она в Domain Computers, а не в Domain Users. Рабочая политика не подошла, запрос дошёл до «Connections to other access servers» и получил отказ с кодом 65 в ту же миллисекунду — на первый же Access-Request, до начала PEAP. Пользователь, вошедший через пару минут, подключился, но политики компьютера при загрузке этот ноутбук по Wi-Fi не получает. Лекарство — политика «Wi-Fi — Domain Computers» из таблицы выше.


Источники

802.1X и RADIUS:

  • RFC 3580 — RADIUS для 802.1X: формат Called-Station-Id «MAC:SSID», VLAN через атрибуты туннеля, Session-Timeout и Termination-Action;
  • RFC 2868 — атрибуты туннеля Tunnel-Type, Tunnel-Medium-Type, Tunnel-Private-Group-ID;
  • RFC 2548 — MS-MPPE-Recv-Key и MS-MPPE-Send-Key, из которых точка берёт PMK;
  • RFC 3748 и RFC 3579 — EAP и его перенос в RADIUS;
  • RFC 1334 — PAP, которым приходит MAB.

Методы EAP и клиент Windows:

Групповая политика и развёртывание:

NPS:


Внутри офиса сеть пускает только своих. Осталось пустить своих снаружи — так же через NPS, с теми же учётными записями, но по другому протоколу и через шлюз, который стоит на границе.

Дальше — часть 28: VPN для удалённого доступа. Шлюз IKEv2 на strongSwan, который сам пароли не проверяет, а отдаёт EAP в NPS по RADIUS; как EAP едет внутри IKE_AUTH и почему здесь EAP-MSCHAPv2 без PEAP; политика NPS для типа порта Virtual, конфигурация swanctl с eap-radius и пулами адресов, сертификат шлюза, профиль VPN на клиенте Windows, и что из части 19 сетевой серии про IPsec и IKEv2 здесь работает без изменений.

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

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