225 lines
20 KiB
Markdown
225 lines
20 KiB
Markdown
# Развёртывание RDP Login Monitor в домене
|
||
|
||
Монитор ставится в **`C:\ProgramData\RDP-login-monitor\`**, задачи планировщика создаёт сам **`Login_Monitor.ps1`** (параметр `-InstallTasks`). Доставку по сети выполняет **`Deploy-LoginMonitor.ps1`**.
|
||
|
||
## Файлы на файловой шаре
|
||
|
||
Создайте каталог, доступный **конечным компьютерам** на чтение (часто учётная запись компьютера домена), например:
|
||
|
||
`\\dc.contoso.local\NETLOGON\RDP-login-monitor\`
|
||
|
||
Внутри должны лежать **три файла** (имена фиксированы):
|
||
|
||
| Файл | Назначение |
|
||
|------|------------|
|
||
| `Login_Monitor.ps1` | Основной скрипт (токен/chat id plain или DPAPI в параметрах). |
|
||
| `version.txt` | **Одна строка** — номер версии пакета на шаре (см. раздел «Версии» ниже). |
|
||
| `Deploy-LoginMonitor.ps1` | Установщик: сравнивает версию, копирует монитор, вызывает `-InstallTasks`, при необходимости запускает процесс монитора. |
|
||
|
||
При выпуске новой сборки обновляйте на шаре **`Login_Monitor.ps1`** и при необходимости **`version.txt`** (логика описана в разделе «Версии»).
|
||
|
||
## Как это работает
|
||
|
||
1. **`Deploy-LoginMonitor.ps1`** определяет корень дистрибутива:
|
||
- параметр **`-SourceShareRoot`** `\\server\share\RDP-login-monitor`, **или**
|
||
- если скрипт запущен по UNC, берётся **родительская папка** этого файла (удобно вызывать шару без параметров).
|
||
|
||
2. Читается **`version.txt`** на шаре и сравнивается с локальной меткой **`C:\ProgramData\RDP-login-monitor\deployed_version.txt`**. Если метки ещё нет — для сравнения подтягивается **`$ScriptVersion`** из уже установленного **`Login_Monitor.ps1`**.
|
||
|
||
3. Если версия на шаре **совпадает** с зафиксированной локально — выход без копирования (быстро, можно при каждой загрузке).
|
||
|
||
4. Если версия на шаре **новее** — останавливаются процессы монитора с каноническим путём → копируется **`Login_Monitor.ps1`** → выполняется **`Login_Monitor.ps1 -InstallTasks`** → записывается **`deployed_version.txt`** → запускается монитор (если не указан **`-SkipStartMonitorAfterUpdate`**).
|
||
|
||
5. Если версия на шаре **старее** локальной — обновление **не выполняется** (защита от отката), пока не указан **`-AllowDowngrade`**.
|
||
|
||
Лог установки: **`C:\ProgramData\RDP-login-monitor\Logs\deploy.log`**.
|
||
|
||
## Опционально на клиенте: `ignore.lst`
|
||
|
||
На каждом компьютере/сервере можно положить файл **`C:\ProgramData\RDP-login-monitor\ignore.lst`** (в том же каталоге, что и **`Login_Monitor.ps1`**). По строкам этого файла монитор **не отправляет оповещения** (Telegram и/или Email — в зависимости от настроенных каналов) для отдельных событий Security:
|
||
|
||
- по умолчанию — **`4624`/`4625`** (шум от известной рабочей станции, тестового пользователя, фиксированного IP);
|
||
- с префиксом **`4740:`** / **`lockout:`** — только блокировки учётной записи (**4740**), в т.ч. по IP из IIS ActiveSync;
|
||
- с префиксом **`all:`** — и входы, и **4740**.
|
||
|
||
Подробный синтаксис — в **[README.md](README.md)** (раздел 7) и **`ignore.lst.example`**.
|
||
|
||
- **`Deploy-LoginMonitor.ps1` с шары `ignore.lst` не доставляет** — при необходимости создавайте файл локально или копируйте своим способом.
|
||
|
||
## Опционально на контроллере домена: блокировки AD (4740)
|
||
|
||
Мониторинг **Security 4740** включается только на том КД, где **установлен и запущен** `Login_Monitor.ps1`, и только если короткое имя узла совпадает с **`$LockoutMonitorDomainController`** в скрипте (после деплоя с шары параметры задаются в локальной копии `Login_Monitor.ps1` на КД).
|
||
|
||
Типичная настройка на КД:
|
||
|
||
- **`$LockoutMonitorDomainController`** — имя этого контроллера (например `DC01`);
|
||
- **`$NetBiosDomainName`**, **`$ExchangeIisLogPath`** — каталог IIS-логов Exchange (ActiveSync, строки **401**);
|
||
- **`$ExchangeIisLogMinutesBeforeLockout`** (по умолчанию 30), **`$ExchangeIisLogTailLines`** (5000), **`$ExchangeServerHostForIisExclude`** — при необходимости.
|
||
|
||
Deploy с NETLOGON обновляет только **`Login_Monitor.ps1`**; пути IIS и имя КД обычно прописывают **один раз** в локальном файле на КД (или через GPO/Configuration Manager), не на всех членах домена.
|
||
|
||
## Heartbeat и «зависший» монитор
|
||
|
||
Файл **`Logs\last_heartbeat.txt`** обновляется по интервалу **`$HeartbeatInterval`** (по умолчанию раз в час). Если обновления нет дольше **`$HeartbeatStaleAlertMultiplier` × $HeartbeatInterval`** (по умолчанию **2×1 ч**), уходит оповещение в настроенные каналы (Telegram/Email). Это не заменяет watchdog-задачу, но сигнализирует, что процесс мог зависнуть без обновления heartbeat.
|
||
|
||
## Задачи планировщика после `-InstallTasks`
|
||
|
||
Параметр **`Login_Monitor.ps1 -InstallTasks`** создаёт две задачи:
|
||
|
||
| Имя | Назначение |
|
||
|-----|------------|
|
||
| **`RDP-Login-Monitor`** | Запуск основного монитора при старте ОС (`Register-ScheduledTask`, триггер «При запуске компьютера»). |
|
||
| **`RDP-Login-Monitor-Watchdog`** | Тот же файл **`Login_Monitor.ps1`** с аргументом **`-Watchdog`**: короткая проверка «жив ли монитор», при необходимости поднимает процесс. |
|
||
|
||
Watchdog регистрируется через **`schtasks.exe /Create /SC MINUTE /MO 5`** (а не через CIM-триггеры PowerShell): на части ОС у объектов триггера нет настраиваемых **`RepetitionInterval`** / длительность «раз и навсегда» режется планировщиком — из‑за этого раньше вторая задача могла не создаваться.
|
||
|
||
Перед созданием выполняется **`schtasks /Delete … /F`** (если задачи ещё не было, сообщение об ошибке подавляется — это нормально).
|
||
|
||
Сразу после регистрации задач вызывается **`schtasks /Run`** и для **основной задачи**, и для **watchdog**: первый запуск не ждёт перезагрузку и ближайшее 5‑минутное окно.
|
||
|
||
Если watchdog срабатывает, а основной монитор «не поднимается», смотрите **`Logs\watchdog.log`** (сообщение о PID и предупреждение, если процесс сразу завершился) и **конец `Logs\login_monitor.log`** — частая причина (исправлено в **1.3.5+**): пустой **`$PSCommandPath`** у процесса, запущенного через **`Start-Process`**; скрипт теперь подставляет путь через **`$PSScriptRoot`**.
|
||
|
||
Один экземпляр монитора фиксируется **файлом блокировки** в **`C:\ProgramData\RDP-login-monitor\.login_monitor_single_instance.lock`** (не Global mutex): так и **SYSTEM** (задача планировщика), и **интерактивный администратор** могут корректно запускать скрипт вручную без «Отказано в доступе» к mutex (версия **1.3.6+**).
|
||
|
||
Проверка:
|
||
|
||
```powershell
|
||
Get-ScheduledTask -TaskName 'RDP-Login-Monitor','RDP-Login-Monitor-Watchdog' -ErrorAction SilentlyContinue
|
||
schtasks /Query /TN "RDP-Login-Monitor-Watchdog"
|
||
```
|
||
|
||
Логи: **`...\Logs\login_monitor.log`**, **`...\Logs\watchdog.log`**.
|
||
|
||
## Запуск Deploy и политики с файловой шары
|
||
|
||
Если при запуске **`Deploy-LoginMonitor.ps1`** или **`Login_Monitor.ps1`** с UNC по **FQDN** (`\\dc.domain.local\...`) PowerShell сообщает про **цифровую подпись** / политику выполнения, чаще всего помогает путь по **короткому имени** контроллера: **`\\DC01\NETLOGON\...`** (клиент относит UNC к интрасети иначе). Параллельно убедитесь, что команда реально с **`powershell.exe -ExecutionPolicy Bypass -File "..."`**.
|
||
|
||
## Версии: `version.txt` и `$ScriptVersion`
|
||
|
||
| Что | Роль |
|
||
|-----|------|
|
||
| **`version.txt` на шаре** | Единственный источник для **`Deploy-LoginMonitor.ps1`**: решение «класть ли новый файл на компьютер». Поднимайте номер **всякий раз**, когда нужно, чтобы доменные машины забрали **новую копию** скрипта с шары — в том числе при мелких правках **без** изменения «видимой» версии в логах. |
|
||
| **`$ScriptVersion` в `Login_Monitor.ps1`** | Версия для **логов и Telegram** (что видит администратор). Меняйте при **значимых** релизах; для полной ясности можно держать ту же строку, что и в **`version.txt`**. |
|
||
|
||
**Типичные сценарии:**
|
||
|
||
- Крупный релиз: обновили **`Login_Monitor.ps1`**, подняли **`$ScriptVersion`** (например `1.4.0`) и записали то же в **`version.txt`** на шаре.
|
||
- Мелкая правка на шаре (опечатка, узкий фикс), не хотите путать отчёты по версии в логах: поднимите только **`version.txt`** (например с `1.3.0` на **`1.3.0.1`** — поддерживаются четырёхкомпонентные номера .NET **Version**). **`$ScriptVersion`** можно не трогать; на клиентах после деплоя в логах по-прежнему будет старая «человеческая» версия, но файл будет актуальным.
|
||
- Идеально поддерживать синхронность **`version.txt`** и **`$ScriptVersion`**, когда правки крупные и версия в логах должна совпадать с дистрибутивом.
|
||
|
||
Итого: **обновляться «по сети» обязан именно `version.txt`**; строка **`$ScriptVersion`** нужна для прозрачности в мониторинге и может совпадать с шарой или отставать по «маркетингу», если вы сознательно крутите только patch в **`version.txt`**.
|
||
|
||
## Групповая политика (GPO): проверенная схема
|
||
|
||
Ниже шаги, которые были проверены на практике для запуска деплоя при старте компьютера.
|
||
|
||
1. Положите три файла на шару (см. выше), например:
|
||
|
||
`\\B26\NETLOGON\RDP-login-monitor\`
|
||
|
||
2. Создайте/настройте GPO и привяжите её к OU с **компьютерами** (не пользователями).
|
||
|
||
3. В GPO откройте:
|
||
**Конфигурация компьютера** → **Политики** → **Конфигурация Windows** → **Сценарии (запуск/завершение)** → **Автозагрузка**.
|
||
|
||
4. На вкладке **«Сценарии PowerShell»** добавьте скрипт:
|
||
|
||
`\\B26\NETLOGON\RDP-login-monitor\Deploy-LoginMonitor.ps1`
|
||
|
||
Параметры можно оставить пустыми, если рядом на шаре лежат `Login_Monitor.ps1` и `version.txt`.
|
||
|
||
5. Security Filtering:
|
||
- можно убрать `Authenticated Users`,
|
||
- добавить группу компьютеров (например `B26\RDP-Login`),
|
||
- убедиться, что у неё есть права **Read** + **Apply group policy**.
|
||
|
||
6. Проверьте, что в группе действительно состоит объект компьютера, например `FVG-PC$`.
|
||
|
||
7. Проверьте доступ на шару/NTFS для контекста компьютера (обычно через `Domain Computers` или целевую группу), потому что startup-скрипт выполняется от имени **SYSTEM**.
|
||
|
||
### Важные нюансы
|
||
|
||
- Кнопка **«Показать файлы»** в свойствах Startup показывает папку GPO в `SYSVOL` (`...\Policies\{GUID}\Machine\Scripts\Startup`).
|
||
- Если вы указали в настройке сценария **UNC путь в NETLOGON**, ваш `.ps1` в этой папке `SYSVOL` не появится — это нормально.
|
||
- После изменения membership компьютера в security-группе часто требуется **перезагрузка** (не только `gpupdate /force`), чтобы обновился токен компьютера.
|
||
|
||
### Как запускать без ожидания перезагрузки
|
||
|
||
- Startup-сценарий GPO штатно отрабатывает при загрузке ОС, но сам `Deploy-LoginMonitor.ps1` после `-InstallTasks` теперь инициирует немедленный `schtasks /Run`:
|
||
- `RDP-Login-Monitor`
|
||
- `RDP-Login-Monitor-Watchdog`
|
||
- Поэтому после фактического запуска deploy монитор и watchdog стартуют сразу.
|
||
|
||
### Серверы без перезагрузок: периодический Deploy
|
||
|
||
Если сервер перезагружается редко, одного Startup-сценария недостаточно для своевременного обновления. В этом случае добавьте отдельную задачу, которая периодически запускает `Deploy-LoginMonitor.ps1` с шары.
|
||
|
||
Если серверов немного, можно обойтись без отдельной задачи: при выпуске новой версии выполнять `Deploy-LoginMonitor.ps1` вручную на нужных серверах.
|
||
|
||
Готовый скрипт в репозитории:
|
||
|
||
- `Install-DeployScheduledTask.ps1`
|
||
|
||
Этот вариант удобен для большого парка серверов, когда обновления нужно подтягивать автоматически и без ручного обхода.
|
||
|
||
Пример (каждые 60 минут и сразу запустить):
|
||
|
||
```powershell
|
||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\Install-DeployScheduledTask.ps1" `
|
||
-TaskName "RDP-Login-Monitor-Deploy" `
|
||
-DeployScriptPath "\\B26\NETLOGON\RDP-login-monitor\Deploy-LoginMonitor.ps1" `
|
||
-RepeatMinutes 60 `
|
||
-RunNow
|
||
```
|
||
|
||
Проверка:
|
||
|
||
```powershell
|
||
schtasks /Query /TN "RDP-Login-Monitor-Deploy" /V /FO LIST
|
||
```
|
||
|
||
Важно: эта задача отвечает только за доставку обновлений (через `version.txt`). За «живость» процесса по-прежнему отвечает `RDP-Login-Monitor-Watchdog`.
|
||
|
||
Пример ручного запуска (для небольшого количества серверов):
|
||
|
||
```powershell
|
||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\B26\NETLOGON\RDP-login-monitor\Deploy-LoginMonitor.ps1"
|
||
```
|
||
|
||
### Диагностика GPO/Startup
|
||
|
||
- События применения политики и startup-сценариев:
|
||
- `Event Viewer -> Applications and Services Logs -> Microsoft -> Windows -> GroupPolicy -> Operational`
|
||
- Логи на клиенте:
|
||
- `C:\ProgramData\RDP-login-monitor\Logs\deploy.log`
|
||
- `C:\ProgramData\RDP-login-monitor\Logs\login_monitor.log`
|
||
- `C:\ProgramData\RDP-login-monitor\Logs\watchdog.log`
|
||
- Быстрая ручная проверка deploy:
|
||
|
||
```powershell
|
||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\B26\NETLOGON\RDP-login-monitor\Deploy-LoginMonitor.ps1"
|
||
```
|
||
|
||
## Ручная проверка
|
||
|
||
```powershell
|
||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\...\Deploy-LoginMonitor.ps1"
|
||
```
|
||
|
||
- **`-WhatIf`** — только сообщение в лог, без копирования.
|
||
- **`-SkipStartMonitorAfterUpdate`** — после обновления не запускать процесс монитора (остаются задачи планировщика и следующая загрузка / watchdog).
|
||
|
||
## Внутренний репозиторий (git.kalinamall.ru)
|
||
|
||
Рабочая копия **`Login_Monitor.ps1`** для домена может содержать **Telegram token/chat id**, **`$LockoutMonitorDomainController`**, **`$NetBiosDomainName`**, **`$ExchangeIisLogPath`** и **`$NotifyOrder`** в открытом виде.
|
||
|
||
- Дистрибутив на шару `NETLOGON` берите из **закрытого** репозитория (`kalinamall` remote), не из публичного GitHub.
|
||
- В **`origin` (GitHub)** не пушьте файл с секретами: перед `git push origin` верните плейсхолдеры или используйте отдельную ветку только для kalinamall.
|
||
- После правок поднимайте **`version.txt`** на шаре (сейчас синхронно с **`$ScriptVersion`** в скрипте).
|
||
|
||
## Безопасность и замечания
|
||
|
||
- ACL на шару: чтение только нужным **компьютерам** / группам; файл **`Login_Monitor.ps1`** может содержать токен — ограничивайте доступ.
|
||
- DPAPI-секреты привязаны к машине: шифровать на каждой цели (Telegram token/chat id, пароль SMTP) или использовать plain на закрытой шаре (см. комментарии в **`Login_Monitor.ps1`**, helper **`Encrypt-DpapiForRdpMonitor.ps1`**).
|
||
- Deploy при ошибках пишет в **`deploy.log`** и завершается с кодом **0**, чтобы не блокировать загрузку ОС; проблемы смотрите по логу на ПК.
|