From f4375c23496b0dac8264a3faf947c3a5291ccd60 Mon Sep 17 00:00:00 2001 From: PTah Date: Fri, 22 May 2026 09:19:26 +1000 Subject: [PATCH] readme and docs editing --- .cursor/rules/01-context-control.md | 28 +++++++++++++ .cursor/rules/02-code-style.md | 13 ++++++ .cursor/rules/powershell-spec.md | 18 ++++++++ .cursor/rules/python-spec.md | 14 +++++++ .cursor/rules/token-saver.md | 22 ++++++++++ .cursor/rules/version-bump.mdc | 44 +++++++++++++++++++ .cursorignore | 65 +++++++++++++++++++++++++++++ DEPLOY.md | 27 ++++++++++-- README.md | 17 ++++---- README_eng.md | 41 ++++++++++++------ 10 files changed, 265 insertions(+), 24 deletions(-) create mode 100644 .cursor/rules/01-context-control.md create mode 100644 .cursor/rules/02-code-style.md create mode 100644 .cursor/rules/powershell-spec.md create mode 100644 .cursor/rules/python-spec.md create mode 100644 .cursor/rules/token-saver.md create mode 100644 .cursor/rules/version-bump.mdc create mode 100644 .cursorignore diff --git a/.cursor/rules/01-context-control.md b/.cursor/rules/01-context-control.md new file mode 100644 index 0000000..bc28dc6 --- /dev/null +++ b/.cursor/rules/01-context-control.md @@ -0,0 +1,28 @@ +--- +description: Global token-saving, cost control, and context management rules +globs: * +--- + +# Global Optimization & Cost Control + +## ?? Context & Local Data +- **Strict file targeting:** Work ONLY with files explicitly provided via `@` or open in the active editor tab. Do not use global codebase search unless requested. +- **Local assets only:** Always work with local copies of repositories and dependencies. Never request external web resources or re-download packages without a explicit build error. +- **Size Limit:** Do not load files larger than 500 lines into the context unless strictly necessary. + +## ?? Git & Commits Management +- **Automatic commits are strictly FORBIDDEN.** Never execute `git commit` or `git push` without an explicit user command. +- Only suggest a commit after phrases like: " ", " ", "Push". +- Before committing: display `git diff --stat` and wait for explicit user confirmation. +- Use Conventional Commits format (`feat:`, `fix:`, `refactor:`, `docs:`). + +## ?? Output Format & Brevity +- **Strictly no fluff:** Omit greetings, apologies, and closing pleasantries. +- **Diff-style only:** Output only modified code fragments, never duplicate unchanged logic or whole files. +- **Extreme brevity:** Explanations must be 1-3 sentences max. Use documentation links instead of long texts. +- If a task doesn't require code, respond strictly with text. If in doubt, ask ONE precise clarifying question. + +## ?? Model Routing Reminder +- Simple questions, explanations, docs ? Use lightweight models (e.g., `gpt-4o-mini`, `claude-3-haiku`). +- Complex code generation, refactoring, and debugging ? Use advanced models (e.g., `claude-3.5-sonnet`). +- Do not switch models without an explicit reason. diff --git a/.cursor/rules/02-code-style.md b/.cursor/rules/02-code-style.md new file mode 100644 index 0000000..1d00ce1 --- /dev/null +++ b/.cursor/rules/02-code-style.md @@ -0,0 +1,13 @@ +--- +description: Code generation syntax restrictions to minimize output tokens +globs: "*.{ts,js,py,cs}" +--- + +# Syntax Optimization + +- **No JSDoc/Docstrings:** Do NOT write documentation, comments, JSDoc, or docstrings for generated functions unless explicitly asked. +- **No logs or prints:** Remove all `console.log`, `print()`, or debugging statements from the final code output. +- **Use concise syntax:** + - In JavaScript/TypeScript: Use arrow functions, optional chaining (`?.`), nullish coalescing (`??`), and destructuring. + - In Python: Use list comprehensions, dict comprehensions, and built-in functions. +- **Minimize imports:** Do not output the `import` statements section if the required packages are standard and already exist in the file. diff --git a/.cursor/rules/powershell-spec.md b/.cursor/rules/powershell-spec.md new file mode 100644 index 0000000..f85d9d6 --- /dev/null +++ b/.cursor/rules/powershell-spec.md @@ -0,0 +1,18 @@ +--- +description: High-density PowerShell script generation rules for minimal token usage +globs: "*.ps1, *.psm1" +--- + +# PowerShell Token Optimization + +- **Use Short Aliases:** Use short aliases instead of full cmdlet names to drastically cut output tokens: + - Use `gc` instead of `Get-Content` + - Use `gci` instead of `Get-ChildItem` + - Use `%` instead of `ForEach-Object` + - Use `?` instead of `Where-Object` + - Use `measure` instead of `Measure-Object` +- **Pipeline Over Loops:** Prefer pipeline chains (`gci | % { ... }`) over multi-line `foreach ($item in $items) { ... }` blocks. +- **No Help/Comments:** Do not generate `.SYNOPSIS`, `.DESCRIPTION`, or comment-based help at the top of scripts. +- **Omit Parameter Names:** Drop explicit parameter names where positional arguments are clear (e.g., use `gc file.txt` instead of `Get-Content -Path file.txt`). +- **Silent Execution:** Do not add verbose logging, `Write-Host`, or `Write-Output` unless explicitly asked to create UI/logs. +- **Preserve CLI Arguments:** Do not duplicate full multi-line `yt-dlp` command-line arguments, format strings, or output templates if they are not the subject of the modifications. Use placeholders or variable references. diff --git a/.cursor/rules/python-spec.md b/.cursor/rules/python-spec.md new file mode 100644 index 0000000..fb0ad8e --- /dev/null +++ b/.cursor/rules/python-spec.md @@ -0,0 +1,14 @@ +--- +description: Ultra-dense Python code generation rules to save output tokens +globs: "*.py" +--- + +# Python Token Optimization + +- **Use Syntactic Sugar:** Prioritize list comprehensions, dict comprehensions, and ternary operators (`x if condition else y`) to keep code on a single line. +- **Built-in Libraries First:** Use standard libraries (`pathlib`, `json`, `subprocess`, `asyncio`) instead of introducing heavy external dependencies unless already in `requirements.txt`. +- **Type Hinting:** Do NOT add type hints (`def func(x: int) -> str:`) unless the existing file strictly uses them. Type hints consume significant tokens. +- **No Format Duplication:** When modifying scripts (like video downloaders), provide only the modified function or class method. Never output the `if __name__ == "__main__":` block or argument parsing logic if they haven't changed. +- **No Docstrings:** Strictly forbid writing `"""docstrings"""` or `# comments` explaining the logic. +- **Preserve yt-dlp Options:** Never rewrite, duplicate, or expand the `ydl_opts` configuration dictionary or custom extraction options. If changes are unrelated to download options, use a placeholder comment like `# ... existing ydl_opts ...` instead of outputting the full dictionary block. + diff --git a/.cursor/rules/token-saver.md b/.cursor/rules/token-saver.md new file mode 100644 index 0000000..c767e11 --- /dev/null +++ b/.cursor/rules/token-saver.md @@ -0,0 +1,22 @@ +--- +description: Global token-saving rules for ultra-concise communication and minimal context usage +globs: * +--- + +# Token-Saving Instructions + +## Communication Strategy +- **Strictly no fluff:** Omit all greetings, pleasantries, apologies, and concluding remarks. +- **Direct answers only:** Start your response immediately with the solution, code block, or direct answer. +- **Extreme brevity:** Keep explanations under 2-3 sentences. Use bullet points instead of long paragraphs. + +## Code Generation Guidelines +- **Do not restate existing code:** Never copy and paste parts of my existing file just to show where to insert changes. +- **Provide diffs only:** Show only the specific lines that need to be changed, added, or deleted. Use brief comments (`// ... existing code ...`) to show placement if necessary. +- **No boilerplate:** Do not generate setup code, imports, or boilerplate unless explicitly requested. +- **Single-line implementations:** Prefer concise, clean, short code syntax where readable (e.g., arrow functions, ternary operators). + +## Code Review and Verification +- Do not explain why the code works unless asked. +- If the solution is simple, output *only* the code block and nothing else. +- If you need more information, ask a single, precise question. Do not list multiple hypotheticals. diff --git a/.cursor/rules/version-bump.mdc b/.cursor/rules/version-bump.mdc new file mode 100644 index 0000000..6b4041f --- /dev/null +++ b/.cursor/rules/version-bump.mdc @@ -0,0 +1,44 @@ +--- +description: Bump версии в csproj и тег релиза vX.Y.Z при обновлениях +alwaysApply: true +--- + +# Версия сборки и теги релиза + +Единственный источник — `VideoDownloader.App/VideoDownloader.App.csproj`. Синхронно обновляй: + +- `Version` (например `0.7.0`) +- `AssemblyVersion` — `x.y.z.0` +- `FileVersion` — `x.y.z.0` +- `InformationalVersion` остаётся `$(Version)` + +## Обычные правки (patch) + +После осмысленного изменения в `VideoDownloader.App` поднимай **patch** на **+0.0.1** (например `0.7.0` → `0.7.1`). Bump в **том же коммите**, что и изменение, где это уместно. + +## Minor / major + +При заметном релизе можно поднять **minor** или **major** по смыслу (например `0.6.x` → `0.7.0`). Не обязательно делать это при каждой мелкой правке. + +## Тег версии при каждом bump (`vX.Y.Z`) — не забывать + +Ветки вида `v0.7.x` **не используем** — маркер релиза — **легковесный или аннотированный тег** с тем же именем. + +При **любом** повышении `` в csproj в том же цикле работы: + +1. Закоммитить bump (вместе с изменениями или коммитом `chore: bump version to X.Y.Z`). +2. Создать тег на **текущем** `HEAD` (после коммита с bump): + `git tag -a vX.Y.Z -m "Release X.Y.Z"` (или `git tag vX.Y.Z` для легковесного тега). + Если тег с таким именем уже существовал локально по ошибке: удалить и создать заново на нужном коммите, либо `git tag -f` осознанно. +3. Запушить **обязательно**: **`git push origin native-code`** и **`git push origin vX.Y.Z`** (первый релиз с этим номером). + Повторный push того же тега на другой коммит на сервере обычно запрещён — bump версии делается новым номером и новым тегом. + +Именование тега: **`v` + полная semver из ``** (пример: `v0.7.2`), без префикса `release/`. + +**Не пушить** только `native-code` без нового **`v*`** — при bump версии всегда создавай и пушь соответствующий тег. + +### Проверка на GitHub + +Релиз по тегу: вкладка **Releases** или список тегов в репозитории; `git checkout v0.7.2` локально даёт ту же ревизию, что и при сборке с этим bump. + +Если на `origin` ещё есть старая **ветка** с тем же имени, что у тега, удаляй явно: `git push origin --delete refs/heads/vX.Y.Z` (иначе Git может не разрешить неоднозначность `vX.Y.Z`). diff --git a/.cursorignore b/.cursorignore new file mode 100644 index 0000000..f5740f9 --- /dev/null +++ b/.cursorignore @@ -0,0 +1,65 @@ +# +node_modules/ +bower_components/ +jspm_packages/ +.npm/ +vendor/ +.pnpm-store/ + +# (Python) +.venv/ +venv/ +env/ +ENV/ +.env/ + +# , +dist/ +build/ +out/ +.next/ +.nuxt/ +.docusaurus/ +.cache/ +.sass-cache/ +.turbo/ +target/ +bin/ +obj/ + +# IDE +.git/ +.svn/ +.idea/ +.vscode/ +.cursor/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# , +*.png +*.jpg +*.jpeg +*.gif +*.svg +*.ico +*.mp4 +*.mp3 +*.pdf +*.zip +*.tar.gz +*.rar +*.exe +*.dll +*.woff +*.woff2 +*.ttf +*.eot + +# (, ) +package-lock.json +yarn.lock +pnpm-lock.yaml +poetry.lock diff --git a/DEPLOY.md b/DEPLOY.md index 1092226..911069c 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -36,10 +36,31 @@ ## Опционально на клиенте: `ignore.lst` -На каждом компьютере/сервере можно положить файл **`C:\ProgramData\RDP-login-monitor\ignore.lst`** (в том же каталоге, что и **`Login_Monitor.ps1`**). По строкам этого файла монитор **не отправляет в Telegram** отдельные события **Security `4624`/`4625`** (например, шум от известной рабочей станции, тестового пользователя или фиксированного IP). +На каждом компьютере/сервере можно положить файл **`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` не доставляет** — при необходимости создавайте файл локально или копируйте своим способом. -- Примеры синтаксиса — в репозитории в файле **`ignore.lst.example`**. + +## Опционально на контроллере домена: блокировки 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` @@ -191,5 +212,5 @@ powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\...\Deploy-LoginMonit ## Безопасность и замечания - ACL на шару: чтение только нужным **компьютерам** / группам; файл **`Login_Monitor.ps1`** может содержать токен — ограничивайте доступ. -- DPAPI-секреты привязаны к машине: шифровать на каждой цели или использовать plain на закрытой шаре (см. комментарии в **`Login_Monitor.ps1`**). +- DPAPI-секреты привязаны к машине: шифровать на каждой цели (Telegram token/chat id, пароль SMTP) или использовать plain на закрытой шаре (см. комментарии в **`Login_Monitor.ps1`**, helper **`Encrypt-DpapiForRdpMonitor.ps1`**). - Deploy при ошибках пишет в **`deploy.log`** и завершается с кодом **0**, чтобы не блокировать загрузку ОС; проблемы смотрите по логу на ПК. diff --git a/README.md b/README.md index 80a6c59..b3ab618 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ # RDP Login Monitor -PowerShell-набор для мониторинга входов в Windows с отправкой уведомлений в Telegram. +PowerShell-набор для мониторинга входов в Windows с уведомлениями в Telegram и/или Email (SMTP). ## Актуальная схема (рекомендуется) - Базовый путь установки: **`C:\ProgramData\RDP-login-monitor\`**. -- Основной скрипт: **`Login_Monitor.ps1`** — журнал Security **`4624`/`4625`** (логика зависит от типа ОС: рабочая станция или сервер/КД), при наличии журнала — **Remote Connection Manager `1149`** (часто актуально для РС с RDP), при роли **RD Gateway** — **`302`/`303`**, на указанном **КД** — **`4740`** (блокировка УЗ + IP из IIS ActiveSync), **ежедневный отчёт** в Telegram (активные сессии через `quser`), **heartbeat**, **ротация логов**, уведомления в Telegram и/или Email. +- Основной скрипт: **`Login_Monitor.ps1`** — журнал Security **`4624`/`4625`** (логика зависит от типа ОС: рабочая станция или сервер/КД), при наличии журнала — **Remote Connection Manager `1149`** (часто актуально для РС с RDP), при роли **RD Gateway** — **`302`/`303`**, на **КД, где запущен монитор** (имя совпадает с **`$LockoutMonitorDomainController`**) — **`4740`** (блокировка УЗ + IP из IIS ActiveSync), **ежедневный отчёт** (активные сессии через `quser`), **heartbeat**, **ротация логов**, уведомления в Telegram и/или Email. - Установка задач: запуск **`Login_Monitor.ps1 -InstallTasks`** создаёт: - `RDP-Login-Monitor` (основной монитор), - `RDP-Login-Monitor-Watchdog` (контроль процесса каждые 5 минут). -- Доменная доставка и обновления: **`Deploy-LoginMonitor.ps1`** + **`version.txt`** с шары `NETLOGON`. После успешного деплоя в приветственном сообщении Telegram может появиться отметка об обновлении (файл **`deploy_last_update.txt`** рядом с логами). +- Доменная доставка и обновления: **`Deploy-LoginMonitor.ps1`** + **`version.txt`** с шары `NETLOGON`. После успешного деплоя в приветственном сообщении (Telegram/Email) может появиться отметка об обновлении (файл **`deploy_last_update.txt`** рядом с логами). - Для полной инструкции по деплою/GPO используйте **[DEPLOY.md](DEPLOY.md)**. -- **`Encrypt-DpapiForRdpMonitor.ps1`** — опционально для подготовки DPAPI-строк токена/chat id. +- **`Encrypt-DpapiForRdpMonitor.ps1`** — опционально для подготовки DPAPI-строк токена/chat id и пароля SMTP (`$MailSmtpPasswordProtectedB64`). ## Что изменилось (важное) @@ -29,13 +29,13 @@ PowerShell-набор для мониторинга входов в Windows с - (для доменного развёртывания отдельно на шаре) `Deploy-LoginMonitor.ps1` и `version.txt`. 3. Откройте `Login_Monitor.ps1` и задайте каналы оповещений: - **Telegram:** `$TelegramBotToken` / `$TelegramChatID` или `...ProtectedB64` - - **Email (SMTP):** `$MailSmtpHost`, `$MailFrom`, `$MailTo`, при необходимости `$MailSmtpUser` / `$MailSmtpPassword` (или `$MailSmtpPasswordProtectedB64` через DPAPI) + - **Email (SMTP):** `$MailSmtpHost`, `$MailFrom`, `$MailTo`, `$MailSmtpPort` (по умолчанию 587), при необходимости `$MailSmtpUser` / `$MailSmtpPassword` (или `$MailSmtpPasswordProtectedB64` через DPAPI), `$MailSmtpStartTls` / `$MailSmtpSsl` - **Порядок:** `$NotifyOrder` — пусто = авто (Telegram → Email, только настроенные); иначе `telegram,email` или `email` и т.п. (допускаются `tg`, `mail`) 4. Запускайте с правами администратора (чтение `Security` журнала и регистрация задач). 5. Логи и служебные файлы будут в: - `C:\ProgramData\RDP-login-monitor\Logs\` 6. (Опционально) Подавление части алертов по списку — см. раздел **«7) ignore.lst»** ниже. -7. (Опционально) Мониторинг блокировок AD на КД — **`$LockoutMonitorDomainController`**, **`$NetBiosDomainName`**, **`$ExchangeIisLogPath`**, **`$ExchangeIisLogMinutesBeforeLockout`** (по умолчанию 30), **`$ExchangeServerHostForIisExclude`**. В оповещении: пользователь из 4740 и IP из IIS за окно до блокировки. В **`ignore.lst`** префикс **`4740:`** или **`all:`** — см. **`ignore.lst.example`**. +7. (Опционально) Мониторинг блокировок AD на КД — **`$LockoutMonitorDomainController`** (короткое имя узла, на котором **установлен и запущен** монитор), **`$NetBiosDomainName`**, **`$ExchangeIisLogPath`**, **`$ExchangeIisLogMinutesBeforeLockout`** (по умолчанию 30), **`$ExchangeIisLogTailLines`** (по умолчанию 5000), **`$ExchangeServerHostForIisExclude`**. В оповещении: пользователь из 4740 и IP из IIS за окно до блокировки. В **`ignore.lst`** префикс **`4740:`** или **`all:`** — см. **`ignore.lst.example`**. 8. Heartbeat: при отсутствии обновления **`Logs\last_heartbeat.txt`** дольше **`$HeartbeatStaleAlertMultiplier` × `$HeartbeatInterval`** (по умолчанию 2×1 ч) — оповещение в Telegram/Email. ## 2) Ручной запуск @@ -69,7 +69,8 @@ powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\ProgramData\RDP-logi - `C:\ProgramData\RDP-login-monitor\Logs\watchdog.log` - Heartbeat: - `C:\ProgramData\RDP-login-monitor\Logs\last_heartbeat.txt` обновляется по интервалу **`$HeartbeatInterval`** (по умолчанию раз в час). -- Ежедневный отчёт: после первого прохождения дневного слота (по умолчанию **09:00**, задаётся **`$DailyReportHour`** / **`$DailyReportMinute`** в `Login_Monitor.ps1`) в Telegram уходит сводка по **`quser`**; метка последнего отчёта — `Logs\last_daily_report.txt`. +- Ежедневный отчёт: после первого прохождения дневного слота (по умолчанию **09:00**, задаётся **`$DailyReportHour`** / **`$DailyReportMinute`** в `Login_Monitor.ps1`) уходит сводка по **`quser`** (Telegram/Email); метка последнего отчёта — `Logs\last_daily_report.txt`. +- Stale heartbeat: если **`last_heartbeat.txt`** не обновлялся дольше **`$HeartbeatStaleAlertMultiplier` × `$HeartbeatInterval`** — оповещение в Telegram/Email (см. п. 8 подготовки). - При старте в Telegram/Email: строка **«Каналы уведомлений»** (фактический порядок доставки), плюс режим RDS/4740 по конфигурации. - Telegram при старте: при установленном **RD Session Host** (или аналогичных компонентах RDS, не только шлюз) — строка про входы по RDP/RDS на этом сервере; при доступном журнале **RD Gateway** — отдельная строка про подключения к **внутренним целевым ПК** через шлюз (302/303). Узел только с ролью RD Gateway не дублирует формулировку «хост сессий». @@ -139,6 +140,6 @@ powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\ProgramData\RDP-logi ## Ключевые слова (для поиска репозитория) -`rdp`, `rd-gateway`, `rdp-gateway`, `rds`, `remote-desktop`, `windows-security-log`, `eventlog`, `event-id-4624`, `event-id-4625`, `event-id-302`, `event-id-303`, `powershell`, `telegram-bot`, `watchdog`, `gpo`, `netlogon`, `domain-deployment`, `windows-server`, `monitoring` +`rdp`, `rd-gateway`, `rdp-gateway`, `rds`, `remote-desktop`, `windows-security-log`, `eventlog`, `event-id-4624`, `event-id-4625`, `event-id-4740`, `event-id-302`, `event-id-303`, `account-lockout`, `active-sync`, `exchange`, `iis`, `smtp`, `email`, `powershell`, `telegram-bot`, `watchdog`, `gpo`, `netlogon`, `domain-deployment`, `windows-server`, `monitoring` diff --git a/README_eng.md b/README_eng.md index 29e05aa..e2905ed 100644 --- a/README_eng.md +++ b/README_eng.md @@ -1,17 +1,17 @@ # RDP Login Monitor -PowerShell toolkit for monitoring Windows logons with Telegram notifications. +PowerShell toolkit for monitoring Windows logons with Telegram and/or Email (SMTP) notifications. ## Recommended layout - Installation root: **`C:\ProgramData\RDP-login-monitor\`**. -- Main script: **`Login_Monitor.ps1`** — Security log **`4624`/`4625`** (behavior depends on OS type: workstation vs server/domain controller), optional **Remote Connection Manager `1149`** when the log is available (often useful for RDP-enabled workstations), **RD Gateway** events **`302`/`303`** when the gateway role/log is present, **daily report** to Telegram (active sessions via `quser`), **heartbeat**, **log rotation**, Telegram alerts. +- Main script: **`Login_Monitor.ps1`** — Security log **`4624`/`4625`** (behavior depends on OS type: workstation vs server/domain controller), optional **Remote Connection Manager `1149`** when the log is available (often useful for RDP-enabled workstations), **RD Gateway** events **`302`/`303`** when the gateway role/log is present, on the **DC where the monitor runs** (hostname matches **`$LockoutMonitorDomainController`**) — **`4740`** (account lockout + IPs from IIS ActiveSync), **daily report** (active sessions via `quser`), **heartbeat**, **log rotation**, alerts via Telegram and/or Email. - Scheduled tasks: run **`Login_Monitor.ps1 -InstallTasks`** to register: - `RDP-Login-Monitor` (main monitor), - `RDP-Login-Monitor-Watchdog` (process health check every 5 minutes). -- Domain delivery and upgrades: **`Deploy-LoginMonitor.ps1`** + **`version.txt`** on a share such as `NETLOGON`. After a successful deploy, the startup Telegram message may include an update note (file **`deploy_last_update.txt`** next to logs). +- Domain delivery and upgrades: **`Deploy-LoginMonitor.ps1`** + **`version.txt`** on a share such as `NETLOGON`. After a successful deploy, the startup notification may include an update note (file **`deploy_last_update.txt`** next to logs). - Full deploy/GPO guidance: **[DEPLOY.md](DEPLOY.md)**. -- **`Encrypt-DpapiForRdpMonitor.ps1`** — optional helper to prepare DPAPI-protected Base64 for the bot token / chat id. +- **`Encrypt-DpapiForRdpMonitor.ps1`** — optional helper to prepare DPAPI-protected Base64 for the bot token / chat id and SMTP password (`$MailSmtpPasswordProtectedB64`). ## Notable behavior @@ -27,13 +27,16 @@ PowerShell toolkit for monitoring Windows logons with Telegram notifications. 2. Copy at least: - `Login_Monitor.ps1` - (for domain rollout on a share) `Deploy-LoginMonitor.ps1` and `version.txt`. -3. Edit `Login_Monitor.ps1` and set the bot token / chat: - - `$TelegramBotToken` or `$TelegramBotTokenProtectedB64` - - `$TelegramChatID` or `$TelegramChatIDProtectedB64` +3. Edit `Login_Monitor.ps1` and configure notification channels: + - **Telegram:** `$TelegramBotToken` / `$TelegramChatID` or `...ProtectedB64` + - **Email (SMTP):** `$MailSmtpHost`, `$MailFrom`, `$MailTo`, `$MailSmtpPort` (default 587), optionally `$MailSmtpUser` / `$MailSmtpPassword` (or `$MailSmtpPasswordProtectedB64` via DPAPI), `$MailSmtpStartTls` / `$MailSmtpSsl` + - **Order:** `$NotifyOrder` — empty = auto (Telegram → Email, configured channels only); otherwise `telegram,email`, `email`, etc. (`tg`, `mail` are accepted) 4. Run elevated (Security log access and task registration). 5. Logs and auxiliary files: - `C:\ProgramData\RDP-login-monitor\Logs\` 6. (Optional) Suppress some Security alerts via **`ignore.lst`** — see **section 7** below. +7. (Optional) AD account lockout monitoring on a DC — **`$LockoutMonitorDomainController`** (short hostname of the machine **where the monitor is installed and running**), **`$NetBiosDomainName`**, **`$ExchangeIisLogPath`**, **`$ExchangeIisLogMinutesBeforeLockout`** (default 30), **`$ExchangeIisLogTailLines`** (default 5000), **`$ExchangeServerHostForIisExclude`**. Alerts include the user from event **4740** and client IPs from IIS within the time window before lockout. In **`ignore.lst`** use prefix **`4740:`** or **`all:`** — see **`ignore.lst.example`**. +8. Heartbeat: if **`Logs\last_heartbeat.txt`** is not updated for longer than **`$HeartbeatStaleAlertMultiplier` × `$HeartbeatInterval`** (default 2×1 h) — alert via Telegram/Email. ## 2) Manual run @@ -66,8 +69,10 @@ For domain deployment from a share you do not configure the scheduler on clients - `C:\ProgramData\RDP-login-monitor\Logs\watchdog.log` - Heartbeat: - `C:\ProgramData\RDP-login-monitor\Logs\last_heartbeat.txt` updates on **`$HeartbeatInterval`** (hourly by default). -- Daily report: after the first daily window (default **09:00**, controlled by **`$DailyReportHour`** / **`$DailyReportMinute`** in `Login_Monitor.ps1`), Telegram receives a `quser` summary; last run marker: `Logs\last_daily_report.txt`. -- Startup Telegram message: with **RD Session Host** (or broader RDS session components, not gateway-only) you get the RDS/RDP session-host line; when the **RD Gateway** log is available you get a separate line about connections to **internal targets** through the gateway (302/303). A gateway-only node does not duplicate the “session host” wording. +- Daily report: after the first daily window (default **09:00**, controlled by **`$DailyReportHour`** / **`$DailyReportMinute`** in `Login_Monitor.ps1`), a `quser` summary is sent (Telegram/Email); last run marker: `Logs\last_daily_report.txt`. +- Stale heartbeat: if **`last_heartbeat.txt`** is stale beyond **`$HeartbeatStaleAlertMultiplier` × `$HeartbeatInterval`** — alert via Telegram/Email (see preparation step 8). +- At startup (Telegram/Email): **notification channels** line (actual delivery order) plus RDS/4740 mode per configuration. +- Startup message (Telegram): with **RD Session Host** (or broader RDS session components, not gateway-only) you get the RDS/RDP session-host line; when the **RD Gateway** log is available you get a separate line about connections to **internal targets** through the gateway (302/303). A gateway-only node does not duplicate the “session host” wording. ## 5) Automatic restart on failure @@ -86,9 +91,9 @@ For domain deployment from a share you do not configure the scheduler on clients ## 7) Suppressing Security alerts: `ignore.lst` -Place a file **`C:\ProgramData\RDP-login-monitor\ignore.lst`** next to **`Login_Monitor.ps1`**. Rules in this list are evaluated **only** for Telegram notifications from Security events **`4624`/`4625`** (successful/failed logons). Built-in exclusions in the script (`ExcludedUsers`, loopback IPs, service-style accounts, etc.) still apply to all event paths; **`ignore.lst`** adds **extra** matches **for 4624/4625 only**. +Place a file **`C:\ProgramData\RDP-login-monitor\ignore.lst`** next to **`Login_Monitor.ps1`**. By default rules apply to **`4624`/`4625`**; prefix **`4740:`** (or **`lockout:`**) — account lockouts only; **`all:`** — logons and **4740**. For **4740**, rule type **`ip:`** is matched against IPs from IIS ActiveSync. Built-in script exclusions still apply to all event types except **4740** (lockouts use **`ignore.lst`** and built-in user checks only). -**RD Gateway (`302`/`303`)**, **RCM `1149`**, the daily report, and heartbeat **are not controlled** by this file (for `1149` the list is not applied, even though a shared filter function runs). +**RD Gateway (`302`/`303`)**, **RCM `1149`**, the daily report, and heartbeat **are not controlled** by this file. ### How the file is loaded @@ -98,7 +103,17 @@ Place a file **`C:\ProgramData\RDP-login-monitor\ignore.lst`** next to **`Login_ - If the line contains **`:`**, the **first** colon splits the line: the left part (trimmed) selects the rule kind, the right part is the value. If the right part is empty, the line is ignored. - If there is **no** colon, the whole trimmed line is one “match-any” value (see below). -### Rule kinds (left part before the first `:`) +### Scope prefix (at the start of the line, before the rule type) + +| Prefix | Events | +| --- | --- | +| *(none)* | **4624**, **4625** | +| `4740:`, `lockout:` | **4740** | +| `all:`, `*:` | **4624**, **4625**, **4740** | + +Example: `4740:user:svc_sync` — do not alert on lockout for that account. + +### Rule kinds (left part before the first `:` after the scope prefix) | Left part (case-insensitive regex fragments) | Event field | | --- | --- | @@ -125,4 +140,4 @@ Explicit **User** / **Workstation** / **Ip** kinds only compare their respective ## Keywords (for discovery) -`rdp`, `rd-gateway`, `rdp-gateway`, `rds`, `remote-desktop`, `windows-security-log`, `eventlog`, `event-id-4624`, `event-id-4625`, `event-id-302`, `event-id-303`, `powershell`, `telegram-bot`, `watchdog`, `gpo`, `netlogon`, `domain-deployment`, `windows-server`, `monitoring` +`rdp`, `rd-gateway`, `rdp-gateway`, `rds`, `remote-desktop`, `windows-security-log`, `eventlog`, `event-id-4624`, `event-id-4625`, `event-id-4740`, `event-id-302`, `event-id-303`, `account-lockout`, `active-sync`, `exchange`, `iis`, `smtp`, `email`, `powershell`, `telegram-bot`, `watchdog`, `gpo`, `netlogon`, `domain-deployment`, `windows-server`, `monitoring`