Skip to content
paulmannPublic

About

RDPAudit 2.0: Windows service plus WinForms configurator that collects RDP logon events, applies 21 alert rules, blocks brute-force IPs automatically and keeps SQLite WAL history.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RDPAudit — Windows RDP Security Monitoring & Auto-Block Platform.

Version License .NET Platform SQLite

Read this in: English · Deutsch · 中文 · हिन्दी · Español · Русский

Edition: Community. Local detection and local response on a single server. What this build contains and what it does not: README-EDITION.md.

RDPAudit is a production-ready Windows platform for monitoring RDP activity and responding to RDP-based threats.
It consists of a Windows Service (background event collection, 21 alert rules, automatic blocking) and a WinForms Configurator (GUI for management, statistics, diagnostics, and policy configuration).


Table of Contents


1. Product Overview

1.1. Purpose

RDPAudit is designed to provide continuous monitoring of RDP activity on Windows servers and workstations. The product runs in the background as a system service, even when no interactive user is logged on, records connection attempts, authentication events, and high-value system changes, evaluates them through 21 security rules, and can automatically block attackers through Windows Firewall and/or MikroTik RouterOS.

Typical use cases:

  • Protecting Internet-exposed RDP endpoints from brute-force attacks
  • Supporting SOC2, ISO 27001, and internal audit requirements for privileged access
  • Detecting account compromise patterns such as a successful logon after repeated failures
  • Identifying accessibility binary backdoors such as Sticky Keys and Utilman abuse
  • Detecting attacks against LSA/LSASS, Kerberos spraying, and RDP port changes
  • Integrating with MikroTik so malicious IPs can be blocked at the network edge

1.2. Solution Architecture

┌──────────────────────────────────────────────────────────────────┐
│                     Windows Event Log                            │
│  Security │ TerminalServices-RemoteConnectionManager │ LocalSession│
└───────────────────────────┬──────────────────────────────────────┘
                            │  EventLogWatcher
                            ▼
┌──────────────────────────────────────────────────────────────────┐
│               RdpAudit.Service  (Windows Service)                │
│                                                                  │
│  EventCollectorHostedWorker ──► EventProcessorWorker              │
│                                   │                             │
│                                   ▼                             │
│                         AlertWorker ──► 21 Alert Rules            │
│                                   │                             │
│                                   ▼                             │
│                         FirewallAutoBlockWorker                  │
│                         (Windows FW + MikroTik REST)             │
│                                   │                             │
│                                   ▼                             │
│                    SQLite  (WAL, %ProgramData%\RdpAudit)         │
│                                   │                             │
│                         Named Pipe IPC Server                    │
└───────────────────────────────────┬──────────────────────────────┘
                                    │  MessagePack over NamedPipe
                                    ▼
┌──────────────────────────────────────────────────────────────────┐
│              RdpAudit.Configurator  (WinForms GUI)               │
│                                                                  │
│  Overview │ Prerequisites │ AuditPolicy │ Service │ Settings     │
│  LiveEvents │ Firewall │ AttackStatistics │ RemoteRdpClients     │
│  AbuseIPDB │ MikroTik │ Logs │ Diagnostics                       │
└──────────────────────────────────────────────────────────────────┘

1.3. Core Capabilities

  • Real-time monitoring through EventLogWatcher subscriptions instead of polling
  • 21 alert rules covering brute force, LSASS attacks, Kerberos spraying, suspicious policy changes, and more
  • Automatic blocking using per-IP Windows Firewall rules with manual reversal support
  • MikroTik integration through RouterOS v7 REST APIs with DPAPI-protected credentials
  • AbuseIPDB reporting with local deduplication and rate-limit awareness
  • Threat-intel reputation checks (Backlog #5) - background AbuseIPDB /api/v2/check lookups with a disk cache and a High-risk mark on Attack Statistics and Live Events
  • Threat analytics aggregated by IP, country, time range, and calculated threat level
  • Session-to-IP correlation for mapping RDP sessions back to source addresses
  • Retention pruning for long-term stability and reduced database growth
  • Backup and restore for configuration state, with no plaintext secrets included
  • Secure Named Pipe IPC restricted to BUILTIN\Administrators
  • Read-only HTTPS REST API (optional, off by default) with bearer-token auth, per-IP rate limiting and an OpenAPI descriptor
  • SIEM export (CEF / LEEF 2.0 / NDJSON) of per-IP events and correlated alerts from the Live Events and Attack Statistics pages

2. System Requirements

2.1. Minimum Requirements

Component Requirement
OS Windows 10 or Windows Server 2016 and newer (x64)
.NET Runtime .NET 8.0 for Windows (x64)
Privileges Local Administrator for service installation and system configuration
Disk 200 MB for binaries plus room for the event database
Memory 64 MB working set for the service under normal load

2.2. Windows Auditing Requirements

RDPAudit depends on Windows Security Auditing to receive the events it analyzes. For correct operation, the following audit categories must be enabled:

Audit Category Subcategory GUID Purpose
Logon / Logoff {0CCE9215-69AE-11D9-BED3-505054503030} Events 4624, 4625, 4634
Account Logon {0CCE9240-69AE-11D9-BED3-505054503030} Kerberos events
Process Creation {0CCE922B-69AE-11D9-BED3-505054503030} Event 4688 and process visibility
Object Access {0CCE9217-69AE-11D9-BED3-505054503030} SACL-backed events such as 4656 and 4663
Policy Change {0CCE922F-69AE-11D9-BED3-505054503030} Firewall and policy change visibility

The Configurator applies these settings automatically by calling auditpol.exe with GUID-based identifiers, which makes the process locale-independent.


3. Solution Layout

3.1. Projects and Layers

Project Type Responsibility
RdpAudit.Core Class Library (net8.0-windows) Entities, EF Core DbContext, migrations, MessagePack IPC contracts, shared helpers
RdpAudit.Service Worker Service (net8.0-windows, win-x64) Event collection, normalization, alert evaluation, auto-blocking, IPC server
RdpAudit.Configurator WinForms App (net8.0-windows) GUI, IPC client, prerequisite checks, service control, configuration workflows
RdpAudit.Web ASP.NET Core App (net8.0-windows) IIS-hosted read-only web dashboard and loopback YARP proxy: bearer injection from the DPAPI vault, security headers, pinned backend TLS
RdpAudit.Core.Tests xUnit Core unit tests
RdpAudit.Service.Tests xUnit Alert rule tests, threshold validation, whitelist coverage, allocation checks
RdpAudit.Web.Tests xUnit Web proxy integration tests: host filter, bearer injection, static CSP/DOM contract
RdpAudit.Benchmarks BenchmarkDotNet Benchmark coverage for hot paths

3.2. Directory Structure

RdpAudit.sln
├── src/
│   ├── RdpAudit.Core/
│   │   ├── Models/              — Entities, enums, projections
│   │   ├── Data/                — AppDbContext, EF Core migrations
│   │   ├── IPC/                 — MessagePack request/response contracts
│   │   └── Services/            — Shared scoring, formatting, and support services
│   ├── RdpAudit.Service/
│   │   ├── Workers/             — BackgroundService workers
│   │   ├── Alerts/              — 21 alert rules
│   │   ├── Firewall/            — Windows Firewall and MikroTik providers
│   │   ├── Collectors/          — Event source wrappers
│   │   └── Program.cs           — DI, Serilog, host wiring
│   ├── RdpAudit.Web/
│   │   ├── wwwroot/             - Static dashboard (index.html + assets)
│   │   ├── Proxy/               - Loopback YARP proxy pipeline and security middleware
│   │   ├── Config/              - WebUiProxyOptions
│   │   └── Program.cs           - Fail-fast WebUI proxy host
│   └── RdpAudit.Configurator/
│       ├── Forms/               — 22 GUI pages
│       ├── IPC/                 — Named Pipe client
│       └── Program.cs           — Elevation, startup, UI bootstrap
├── tests/
│   ├── RdpAudit.Core.Tests/
│   ├── RdpAudit.Service.Tests/
│   ├── RdpAudit.Web.Tests/
│   └── RdpAudit.Benchmarks/
├── docs/
│   ├── 90-windows-validation.md
│   └── 91-troubleshooting.md
└── publish.ps1

4. Quick Start

4.1. Build

git clone https://github.com/paulmann/RDPAudit.git
cd RDPAudit
dotnet build RdpAudit.sln -c Release

4.2. Install the Service

# Publish binaries
./publish.ps1

# Copy the service payload into Program Files
Copy-Item -Recurse publish/Service "$env:ProgramFiles\RdpAudit\Service"

# Install as a Windows Service manually, or use the Configurator UI
sc.exe create RdpAudit binPath= "$env:ProgramFiles\RdpAudit\Service\RdpAudit.Service.exe" start= auto
sc.exe description RdpAudit "RDP Security Monitoring & Auto-Block Service"
sc.exe start RdpAudit

4.3. First Launch of the Configurator

publish/Configurator/RdpAudit.Configurator.exe

On first launch, the recommended sequence is:

  1. Open Prerequisites and verify required channels and platform settings.
  2. Open Audit Policy and apply the required audit subcategories through auditpol.exe.
  3. Open Service and install or start the Windows Service.
  4. Open Settings and tune alert thresholds, trusted IPs, retention, and integrations.

5. RdpAudit.Service — Monitoring Service

5.1. Event Collection

The service uses System.Diagnostics.Eventing.Reader.EventLogWatcher to subscribe to relevant events in real time. The design is already abstracted behind event source interfaces so the collection backend can later move to ETW-based ingestion without rewriting the rest of the pipeline.

Monitored channels:

  • Security
  • Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational
  • Microsoft-Windows-TerminalServices-LocalSessionManager/Operational

5.2. Tracked Event IDs

Event ID Channel Description
4624 Security Successful logon, especially Logon Type 10
4625 Security Failed logon
4634 Security Logoff
4647 Security User-initiated logoff
4648 Security Logon with explicit credentials
4688 Security Process creation
4720 Security User account created
4723 / 4724 Security Password change / password reset
4740 Security Account lockout
4769 Security Kerberos service ticket request
4771 Security Kerberos pre-authentication failure
4776 Security NTLM authentication
4954 Security Windows Firewall rule or policy change
1149 TerminalServices-RCM RDP connection with source IP
21, 23, 24, 25 TerminalServices-LSM Session start, reconnect, disconnect, end

5.3. Data Storage (SQLite)

The database is stored at %ProgramData%\RdpAudit\rdpaudit.db.

SQLite settings:

PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;

Primary tables:

Table Purpose
RawEvents Normalized security and RDP events
RdpConnectionFacts Connection facts with IP, user, and outcome
AuthAttemptFacts Authentication attempt facts
Sessions RDP session records
SessionIpCorrelations Session-to-IP mapping
AttackStats Aggregated attack statistics by source
ActiveBlocks Currently active automatic blocks
Alerts Alert history
WhitelistEntries Trusted IP and CIDR entries
BlocklistEntries Persistent block rules and sources
AbuseIpDbReportHistory AbuseIPDB report history
OperationLogs Operational log entries surfaced in the GUI
DbProps Key-value metadata store
Bookmarks Crash-recovery bookmarks for event processing
LoginRules Work-hours and logon policy rules

Write strategy: the hot path uses raw SqliteCommand with explicit transactions and batched writes.

Bookmark durability: bookmarks are flushed every 100 events and every 30 seconds, which minimizes loss after a crash or power interruption.

5.4. Alerting System — 21 Rules

Each rule is implemented as a dedicated alert evaluator and participates in a common rule pipeline.

# Rule ID Severity Description
1 BRUTE_FORCE High Failed logons from the same source exceed threshold
2 BRUTE_FORCE_NTLM High NTLM brute-force with cooldown logic
3 KERBEROS_SPRAY High Kerberos password spraying behavior
4 SUCCESSFUL_AFTER_FAILS Medium Successful logon after repeated failures
5 OFF_HOURS_LOGIN Medium Logon outside approved working hours
6 ACCOUNT_LOCKOUT Medium Account lockout event
7 NEW_ACCOUNT_CREATED Medium New local or domain account created
8 PASSWORD_RESET Low Password reset or password change
9 MULTIPLE_ACCOUNTS_SAME_IP High Username spray from one source IP
10 STICKY_KEYS_BACKDOOR Critical Accessibility-binary backdoor behavior
11 LSASS_ACCESS Critical Suspicious handle access to LSASS
12 LSASS_PPL_TAMPER Critical Attempt to weaken LSASS PPL protection
13 RDP_PORT_CHANGED High Registry-based RDP port change detected
14 FIREWALL_RULE_CHANGED Medium Firewall rule or policy changed
15 EXPLICIT_CREDENTIALS Medium Explicit credential usage pattern
16 LOGON_TYPE_NETWORK Low Network logon to a protected system
17 CONCURRENT_SESSIONS Low Excess concurrent session count
18 GEO_ANOMALY Medium Logon from a disallowed or unexpected geography
19 IP_REPUTATION High Source IP appears in known blocklists
20 SESSION_HIJACK_SUSPECT High Session correlation anomaly
21 RAPID_RECONNECT Medium Repeated reconnect activity from the same IP

5.4.1. PRIVILEGED_LOGIN hardening

The PRIVILEGED_LOGIN rule (Event 4672 - SeDebug / SeTcb assigned at logon) is hardened against the start-of-service well-known-SID storm (identical SYSTEM alerts with no source IP):

  • Exact SID filter - S-1-5-18 (SYSTEM), S-1-5-19 (LOCAL SERVICE) and S-1-5-20 (NETWORK SERVICE) are rejected by exact SID read from the normalized Details JSON (subjectUserSid), never by localized account names.
  • Network context required - the event must carry a non-empty SourceIp and a network logon type (3 / 7 / 10). A missing LogonType (Windows 4672 has no field of its own) falls back to correlating the matching Security 4624 via SubjectLogonId == TargetLogonId.
  • Suppression window - identical triggers per (user, source ip, logon type) are suppressed inside PrivilegedLoginSuppressionWindowMinutes (default 5); when the window expires, a single summary alert carries the suppressed count.
  • Per-minute alert budget - PrivilegedLoginRateLimitPerMinute (default 20) caps the output; throttling is logged once per minute.
  • Historical age gate - events older than AlertEventMaxAgeMinutes (default 5) remain persisted as RawEvent facts but never alert (applied by AlertWorker to all rules).
  • Zero-allocation rejection path - EvaluateAsync is a non-async method returning a cached null-task singleton, so rejected evaluations allocate nothing.

5.5. Windows Firewall Auto-Blocking

When rules such as BRUTE_FORCE, BRUTE_FORCE_NTLM, or IP_REPUTATION are triggered, the service can create a per-IP inbound block rule.

netsh advfirewall firewall add rule `
  name="RdpAudit_Block_<IP>" `
  dir=in action=block remoteip=<IP> `
  protocol=any enable=yes

Implementation characteristics:

  • Idempotent rule creation
  • Input sanitization before shell execution
  • Manual removal through the GUI
  • Full auditing through ActiveBlocks and OperationLogs

5.6. Named Pipe IPC

Pipe name: \\.\pipe\RdpAuditService

Security model: only BUILTIN\Administrators are allowed to connect.

Protocol: MessagePack request and response contracts defined in RdpAudit.Core.

Operational notes:

  • The GUI never writes service-owned configuration files directly.
  • Settings are sent over IPC and committed atomically by the service.
  • Connection deadlines prevent the Configurator from hanging indefinitely.
  • The pipe is served by IpcServerWorker, which requests MaxConcurrent + 1 OS instances so the always-listening standby pipe never competes with a connected handler. Win32 ERROR_PIPE_BUSY (231) is classified as "instance cap reached", not as AV/EDR interception; saturation drains automatically as handlers complete.
  • Each worker instance writes observable lifecycle facts to %ProgramData%\RdpAudit\logs\ipc-startup.log: instance constructed / ExecuteAsync entered / ExecuteAsync exiting (pid, instanceId, entryCount, exitCount, iteration, activeHandlers, livePipes, stoppingTokenCancelled, hostApplicationStoppingCancelled, exitReason, lifetimeMs). These fields prove whether one process ever ran more than one worker or host instance.

5.7. Reliability and Resilience

  • Exponential backoff for transient database contention such as SQLITE_BUSY
  • End-to-end CancellationToken propagation across async flows
  • Every hosted worker is wrapped in TimedHostedService and writes startup-sequence.log begin/end/failure marks
  • IpcServerWorker logs per-instance lifecycle breadcrumbs so a repeated ExecuteAsync entered in one PID can be attributed to one or multiple worker/host instances
  • Graceful shutdown on service stop
  • EF Core migrations applied at startup
  • Event Log source registration during installation

5.8. REST API (read-only)

The service can expose an optional read-only HTTPS REST API (Kestrel, off by default) for monitoring agents and scripts. It answers only GET/HEAD and reuses the same audited read commands as the named pipe, so the REST surface has no write paths.

  • Endpoints: /healthz (anonymous), /api/status, /api/alerts, /api/sessions, /api/addresses, /api/attacks, /api/config (secrets masked), /api/events (bounded, filtered, ordered page) and /openapi/v1.json (committed OpenAPI 3.0 descriptor).
  • Authentication: static bearer token (Api.Token, DPAPI-protected) with WWW-Authenticate: Bearer realm="rdpaudit" on 401.
  • Transport: HTTPS only. Listener defaults to 127.0.0.1:8443; a TLS certificate in LocalMachine\My is selected by Api.CertificateThumbprint / Api.CertificateSubject. Non-loopback listeners log an explicit risk warning at startup.
  • Hardening: per-IP fixed-window rate limit (Api.RateLimitPerMinute), connection cap (Api.MaxConnections), security headers, and RFC 9457 problem+json error bodies for every non-200 response.
  • Fail-closed startup: Api.Enabled=false (default) or any missing prerequisite (token/certificate/address) means no listener at all.

Configuration is in the Api section of appsettings.json. Full reference: docs/40-options.md (ApiOptions) and docs/51-rest-api.md (endpoints, errors, authentication, operation).


6. RdpAudit.Configurator — GUI

The Configurator runs elevated and communicates with the service strictly through the Named Pipe IPC channel.

6.1. Overview Tab

The Overview tab is the operator dashboard. It summarizes service state, current block counts, recent alerts, and recent event volume.

6.2. Prerequisites Tab

The Prerequisites tab checks the required Windows conditions:

  • All seven monitored event-log channels present and enabled (Security, System, and the Terminal Services / RDP channels)
  • Required audit-policy subcategories applied (object access + the five-subcategory baseline)
  • Service installed and reachable

A disabled channel offers a wevtutil sl /enabled:true fix. A channel that does not exist on this Windows build/SKU (for example TerminalServices-Gateway on a host without the RD Gateway role) is reported as missing with no automatic fix, so the tab never offers an enable button for a channel this Windows edition cannot create. Each fixable failure can be applied directly from the UI.

6.3. Audit Policy Tab

The Audit Policy tab reads the current Windows audit configuration and applies the required subcategories through GUID-based auditpol.exe calls. It also handles SACL setup for high-value registry locations and IFEO paths tied to RDP abuse detection.

6.4. Service Tab

The Service tab supports:

  • Install and uninstall
  • Start, stop, restart
  • Service status display
  • Startup mode control

6.5. Settings Tab

The Settings tab exposes operational configuration, including:

  • Alert thresholds
  • Brute-force windows
  • Work-hour definitions
  • Data retention windows
  • AbuseIPDB settings
  • MikroTik settings
  • Geolocation and whitelist settings

Changes are submitted over IPC and applied atomically by the service.

6.6. Live Events Tab

The Live Events tab provides a tail-style stream of real-time events with color coding for failures, warnings, and successful activity. It supports filtering by Event ID and source IP. A High risk column shows the cached threat-intel mark (Stage 15) for each source IP.

6.7. Firewall Tab

The Firewall tab surfaces active blocks from ActiveBlocks and supports:

  • Viewing blocked IPs, reasons, and providers
  • Manually adding block entries
  • Removing blocks with confirmation
  • Importing or exporting blocklists

6.8. Attack Statistics Tab

The Attack Statistics tab presents aggregated attack data:

  • Top attacking IPs
  • Threat level scoring
  • Time-based charts
  • Country-level grouping
  • CSV export support
  • High risk column backed by the cached threat-intel mark (Stage 15)

Threat level is calculated through the scoring logic in AttackThreatScoring.

6.9. Remote RDP Clients Tab

The Remote RDP Clients tab correlates source IPs, connection counts, usernames, and historical RDP sessions. It is intended to separate legitimate remote administration from noisy attack traffic.

6.10. AbuseIPDB Tab

The AbuseIPDB tab manages:

  • API key configuration
  • Manual and automatic report workflows
  • Report history with deduplication
  • Rate-limit-aware status and validation
  • Threat-intel reputation checks (/api/v2/check) with cache status, daily usage and the High-risk threshold (Backlog #5)

Secrets are never displayed back in plaintext.

6.11. MikroTik Tab

The MikroTik tab configures RouterOS v7 REST integration:

  • Router address and port
  • DPAPI-protected credentials
  • TLS validation behavior
  • Address-list synchronization
  • Connectivity testing

6.12. Logs Tab

The Logs tab displays operational entries from OperationLogs, grouped by severity:

  • Info
  • Warning
  • Error
  • Critical

6.13. Diagnostics Tab

The Diagnostics tab provides operator-facing health data:

  • Worker state
  • IPC health
  • Database size and status
  • Integration checks
  • Diagnostic export support

6.14. Session Map Tab

The Session Map tab lets a SOC operator inspect one historical RDP session as a chronological timeline (Backlog #6). Selecting a fact from the bounded session list (served by the existing ListConnectionFacts command with IP / User filters) loads the GetSessionTimeline response and shows it twice:

  • Event table - time, kind (logon start / connected / reconnected / disconnected / logoff / process / file / other), event id, process, object and the explicit correlation method. UserWindow-correlated rows are tinted amber so the lower forensic confidence is always visible; raw DEBUG detail text is available in a tooltip only when the service runs with DEBUG mode on.
  • Gantt panel - a built-in GDI+ timeline with a UTC time axis, colour-coded lanes, legend, a dashed "now" beam for active sessions and a TRUNCATED badge when the server-side activity cap (50..2000, default 500) fired.

The command is strictly read-only and adds no tables or migrations; see docs/54-session-map.md for the contract, correlation rules, threat model and rollback guidance.

6.15. Notifications Tab

The Notifications tab configures the elevated RdpAudit.Notifier tray app:

  • Enable tray notifier - master switch; when off the notifier exits silently.
  • Start with Windows - registers / removes the RdpAudit.Notifier logon task through schtasks (ONLOGON, /RL HIGHEST).
  • Poll interval - service polling cadence in seconds (clamped 1..60).
  • Minimum severity - alerts below this severity are never shown.
  • Max toasts per minute - sliding-window rate cap (clamped 1..60); surplus alerts collapse into one aggregate toast.
  • Use native toasts - prefer WinRT toasts over tray balloon tips; the notifier falls back to balloons when the native channel is unavailable.
  • Alerts / Events sub-tabs - per-rule and per-event visibility maps.

Save / Refresh flow through the IPC commands GetNotificationSettings (78) and SaveNotificationSettings (79); the service clamps values, falls back the severity to High and persists only the RdpAudit.Notifications section of appsettings.json. The notifier polls the service over the named pipe, degrades to a safe interval while it is unreachable, and never edits the database.


6.16. Web Access Tab

The Web Access tab (placed right after Service) is the entry point for the read-only IIS-hosted web dashboard. It is privacy-first: everything stays off until the operator explicitly opts in.

  • Show Web Access - persists the operator's visibility choice; off by default and only stored when the operator toggles it.
  • Allow management from the web - phase-gated: visible but locked until a later management phase unlocks it; the stored preference can never become true before that gate opens.
  • Refresh status - re-runs the fail-closed IIS probe (registry InetStp, read-only dism /English /Online /Get-FeatureInfo, W3SVC service check) and shows a one-line verdict.
  • Install IIS - guided, idempotent installation driven by IisInstallPlan, the single source of truth for both the pre-run checklist and the executed workflow. The progress window lists every item before anything runs and paints a tick or a cross per item: elevation, the static DISM feature set (IIS-WebServerRole, IIS-WebServer, IIS-StaticContent, IIS-DefaultDocument, IIS-HttpErrors via dism ... /NoRestart), the IIS management tools (IIS-WebServerManagementTools, IIS-ManagementScriptingTools, which provide appcmd.exe used by Configure IIS), the ASP.NET Core Hosting Bundle installed through winget install --id Microsoft.DotNet.HostingBundle.8 --exact as the single source of the native AspNetCoreModuleV2, and a final verification of what is actually on the machine. The bundle step is skipped when the module is already present, so winget is never called twice for the same machine, and DISM exit code 3010 is reported as a warning asking for a restart - never as success.
  • Configure IIS - guided setup of the RdpAuditWebUi site: requires elevation plus the ASP.NET Core Module v2 (Hosting Bundle), resolves or creates the loopback HTTPS certificate, stores the web token only as a DPAPI-protected envelope in the service appsettings.json, stages the RdpAudit.Web payload into %ProgramData%\RdpAudit\WebUI, binds the site to https://127.0.0.1:443 and restarts the service.

Both workflow buttons stay disabled until the probe can actually declare the IIS state. The browser never sees the bearer token: the in-process YARP proxy injects it from the machine-scope DPAPI vault and strips any browser-supplied Authorization header; a Host filter additionally rejects non-loopback host names (DNS-rebinding defense).

7. RdpAudit.Core — Shared Library

7.1. Data Models

Key entities include:

Type Description
RdpConnectionFact RDP connection fact record
AuthAttemptFact Authentication attempt fact
Session RDP session metadata
SessionIpCorrelation Session-to-IP mapping
AttackStat Aggregated attack metrics
AttackThreatLevel Threat level enum
AttackThreatScoring Threat scoring logic
AttackStatProjection UI-facing attack statistics projection
ActiveBlock Active block record
BlocklistEntry Persistent blocklist entry
WhitelistEntry Trusted IP or CIDR entry
Alert Alert record
AbuseReport AbuseIPDB report payload
AbuseIpDbReportHistory Report history and deduplication
RawEvent Normalized raw event record
OperationLog Service operation log record
LoginRule Time-based access rule
Bookmark Event processing bookmark
DbProp Key-value metadata record
ThreatIntelLookup Cached /api/v2/check reputation snapshot per IP (Stage 15)
ThreatIntelUsageCounter Persisted daily /check usage budget counter (Stage 15)
Address IP address and related metadata

7.2. Entity Framework Core and Migrations

  • EF Core 8 with SQLite
  • AppDbContext for schema ownership and query support
  • Automatic migration application at service startup
  • EF Core reserved for configuration, migrations, and UI reads
  • Hot-path writes handled through raw SQLite commands and explicit transactions

7.3. IPC Contracts (MessagePack)

IPC requests and responses are serialized with MessagePack. Representative contracts include:

  • GetStatusRequest / GetStatusResponse
  • GetEventsRequest / GetEventsResponse
  • GetFirewallBlocksRequest / GetFirewallBlocksResponse
  • AddBlockRequest / AddBlockResponse
  • RemoveBlockRequest / RemoveBlockResponse
  • GetSettingsRequest / GetSettingsResponse
  • SaveSettingsRequest / SaveSettingsResponse
  • GetAttackStatsRequest / GetAttackStatsResponse
  • GetOperationLogsRequest / GetOperationLogsResponse

8. External Integrations

8.1. AbuseIPDB

RDPAudit can report attacking IPs to AbuseIPDB when brute-force or high-confidence malicious behavior is detected.

Design notes:

  • API keys are stored as DPAPI-protected values
  • Duplicate reports are suppressed through local history
  • Rate limits are respected
  • Report categories are configurable

RDPAudit can also look up IP reputation on read: the opt-in threat-intel feature (AbuseIpDb.CheckEnabled) runs GET /api/v2/check through a background worker, warms a disk cache for public attack-source IPs, and surfaces a High-risk mark on the Attack Statistics and Live Events grids. The API key is sent only in the Key header and never logged.

8.2. MikroTik RouterOS v7

RDPAudit can push malicious IPs into a MikroTik address list through the RouterOS v7 REST API.

Design notes:

  • Works over HTTPS REST endpoints
  • Supports configurable TLS validation
  • Stores credentials through DPAPI protection
  • Avoids duplicate address-list entries
  • Falls back gracefully when the router is unavailable

9. Auto-Blocking Model

9.1. Trigger Thresholds

Default behavior:

  • 10 failed logons from the same IP within 10 minutes triggers a block
  • Thresholds are configurable through Settings
  • Whitelisted sources are excluded before a block is applied

9.2. Local Windows Firewall

Provider: WindowsFirewallProvider
Action:   Create inbound rule "RdpAudit_Block_<IP>" (block, any protocol)
Reverse:  Remove rule by name
Verify:   netsh advfirewall firewall show rule name="RdpAudit_Block_<IP>"

9.3. Remote MikroTik Firewall

Provider: MikroTikFirewallProvider
Action:   PUT /rest/ip/firewall/address-list { address: <IP>, list: "RdpAudit-Blocklist" }
Reverse:  DELETE /rest/ip/firewall/address-list/<id>
Verify:   GET /rest/ip/firewall/address-list?address=<IP>

9.4. Whitelist Protection for Trusted IPs

  • Supports single IPs and CIDR ranges
  • Evaluated before any block is created
  • Managed through the GUI
  • Stored in WhitelistEntries with audit-friendly metadata

10. Data Maintenance

10.1. Retention Pruning

A pruning worker periodically deletes stale records.

Table Default Retention Configurable
RawEvents 90 days Yes
Alerts 180 days Yes
AbuseIpDbReportHistory 365 days Yes
ActiveBlocks (inactive) 30 days Yes
AttackStats 365 days Yes

Implementation notes:

  • Batched deletes
  • Exponential backoff on SQLITE_BUSY
  • Cancellation support
  • Operation logging

10.2. Backup and Restore

The backup workflow captures configuration state, not the event database.

Included in backup:

  • appsettings.json with DPAPI envelopes only
  • Audit policy export
  • Relevant registry keys
  • Service configuration metadata

Not included:

  • rdpaudit.db

A pre-restore safety snapshot is created before any restore operation is executed.


11. Security and Auditing

11.1. Access Control

Component Access Model
RdpAudit.Service Runs as SYSTEM or a dedicated service identity
Named Pipe IPC BUILTIN\Administrators only
RdpAudit.Configurator Requires elevation
SQLite DB Restricted to SYSTEM and Administrators
appsettings.json Restricted to SYSTEM and Administrators

11.2. SACL Configuration

The Configurator sets SACLs on high-value targets so sensitive changes become auditable:

  • IFEO accessibility keys
  • RDP-Tcp registry configuration
  • Lsa registry configuration

This supports detection of Sticky Keys backdoors, RDP port changes, and LSASS/PPL tampering.

11.3. Secret Protection (DPAPI)

  • AbuseIPDB keys and MikroTik credentials are protected with Windows DPAPI
  • Only DPAPI envelopes are stored in configuration
  • The GUI does not reveal plaintext secrets
  • Backups include protected values, not decrypted ones

12. Configuration

12.1. appsettings.json

{
  "RdpAudit": {
    "DatabasePath": "%ProgramData%\\RdpAudit\\rdpaudit.db",
    "EnabledEventIds": ,
    "AlertRules": {
      "BruteForce": {
        "IsEnabled": true,
        "FailThreshold": 10,
        "WindowSeconds": 600
      },
      "OffHoursLogin": {
        "IsEnabled": true,
        "WorkHoursStart": "08:00",
        "WorkHoursEnd": "20:00",
        "WorkDays": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
        "TimeZoneId": "UTC"
      }
    },
    "Alerts": {
      "EnablePrivilegedLoginDetection": true,
      "PrivilegedLoginSuppressionWindowMinutes": 5,
      "PrivilegedLoginRateLimitPerMinute": 20,
      "AlertEventMaxAgeMinutes": 5
    },
    "AutoBlock": {
      "IsEnabled": true,
      "Providers": ["WindowsFirewall"],
      "BlockTtlHours": 0
    },
    "Retention": {
      "RawEventsDays": 90,
      "AlertsDays": 180,
      "AttackStatsDays": 365
    },
    "AbuseIpDb": {
      "Enabled": false,
      "ReportAttacks": false,
      "ApiKey": "",
      "BaseUrl": "https://api.abuseipdb.com",
      "EndpointUrl": "https://api.abuseipdb.com/api/v2/report",
      "TimeoutSeconds": 15,
      "MaxReportsPerMinute": 60,
      "MaxReportsPerHour": 100,
      "MaxReportsPerDay": 500,
      "DeduplicationWindowMinutes": 15,
      "CacheLookups": true,
      "CacheTtlMinutes": 60,
      "ReportThreshold": 80,
      "MinThreatScore": 60.0,
      "MinFailedAttempts": 10,
      "ReportCategories": [18, 22],
      "ReportDedupeEnabled": true,
      "ReportCooldownHours": 24,
      "CheckEnabled": false,
      "CheckMaxLookupsPerMinute": 30,
      "CheckMaxLookupsPerDay": 500,
      "CheckMaxAgeInDays": 30,
      "CheckWorkerIntervalSeconds": 300
    },
    "MikroTik": {
      "IsEnabled": false,
      "Address": "",
      "Port": 443,
      "UsernameDpapi": "",
      "PasswordDpapi": "",
      "VerifyTls": true,
      "AddressListName": "RdpAudit-Blocklist"
    }
  },
  "Serilog": {
    "MinimumLevel": { "Default": "Information" },
    "WriteTo": [
      { "Name": "File", "Args": { "path": "%ProgramData%\\RdpAudit\\logs\\rdpaudit-.log", "rollingInterval": "Day" } },
      { "Name": "EventLog", "Args": { "source": "RdpAudit", "logName": "Application" } }
    ]
  }
}

12.2. Environment Variables

You can override configuration values through environment variables, which is useful for automated deployment and diagnostics:

RDPAUDIT_RdpAudit__LogLevel=Debug
RDPAUDIT_RdpAudit__AlertRules__BruteForce__FailThreshold=5

13. Debugging and Diagnostics

13.1. Console Mode

When a debugger is attached, the service can run as a console application instead of a formal Windows Service.

cd src\RdpAudit.Service
dotnet run --configuration Debug

13.2. Serilog Logs

Logs are written to:

  • %ProgramData%\RdpAudit\logs\rdpaudit-<date>.log
  • Windows Event Log → Application, source RdpAudit

To increase verbosity:

$env:RDPAUDIT_RdpAudit__LogLevel = "Debug"

13.3. Direct SQLite Access

& "C:\Program Files\DB Browser for SQLite\DB Browser for SQLite.exe" `
  "$env:ProgramData\RdpAudit\rdpaudit.db"

Useful queries:

SELECT * FROM RawEvents ORDER BY TimeUtc DESC LIMIT 100;

SELECT * FROM ActiveBlocks WHERE Status = 'Active';

SELECT SourceIp, SUM(FailCount) AS Fails
FROM AttackStats
GROUP BY SourceIp
ORDER BY Fails DESC
LIMIT 20;

13.4. Diagnostics Tab

The Diagnostics UI exposes:

  • Events-per-second counters
  • Worker status
  • IPC state
  • Database health
  • External integration reachability

14. Build and Test

14.1. Build

dotnet build RdpAudit.sln -c Release
dotnet build src/RdpAudit.Service/RdpAudit.Service.csproj -c Release

14.2. Tests

dotnet test RdpAudit.sln -c Release
dotnet test RdpAudit.sln -c Release --collect:"XPlat Code Coverage"
dotnet test tests/RdpAudit.Service.Tests/RdpAudit.Service.Tests.csproj

Each alert-rule test should validate:

  1. Threshold boundary behavior
  2. Whitelist bypass behavior
  3. Zero managed allocations across repeated evaluations

14.3. Publish

./publish.ps1

Expected output:

publish/
├── Service/
└── Configurator/

15. Troubleshooting

Detailed guidance: docs/91-troubleshooting.md

Symptom First Diagnostic Step
Service does not start Check sc.exe query RdpAudit, then review the Application Event Log
No live events appear Open Prerequisites and confirm audit configuration
GUI cannot connect Verify the service is running and the pipe ACL is correct
sc.exe returns 1639 Re-check quoting in the service binary path
AbuseIPDB returns HTTP 429 The API rate limit has been reached
MikroTik TLS failure Disable verification for self-signed certs or install the CA cert
SQLITE_BUSY appears Short-term contention is expected and retried automatically
Audit policy displays ? Re-apply through the Audit Policy tab
ProgramData ACL issues Repair folder ACLs for SYSTEM and Administrators

See also: docs/90-windows-validation.md


16. Roadmap (v2.0 → v3.0)

Feature Status
ETW ingestion (OpenTrace / ProcessTrace) Planned
Direct EVTX parsing with Span<byte> Planned
Lock-free MPMC ring buffer Planned
SIMD CIDR and parsing acceleration Planned
Zero-allocation event normalization Planned
Network-layer MS-RDPBCGR / RDPEUDP visibility Research
Blazor-based web UI Planned
Elastic / OpenSearch integration Roadmap
Central multi-server collector Roadmap

17. License and Author

License: Business Source License 1.1

RDPAudit Community is source-available. You may copy, modify, redistribute and use it for non-production purposes; the Additional Use Grant written into LICENSE additionally allows production use, except offering the software to third parties as a commercial hosted or managed service. On 2030-10-25 this version converts to the Apache License 2.0.

The Pro and Enterprise editions are proprietary and are not covered by this licence - each carries its own terms. Which capability belongs to which edition is documented in docs/editions.md.

Author: Mikhail Deynekin

Repository: github.com/paulmann/RDPAudit

Related resources:


© 2025–2026 Mikhail Deynekin. Released under the Business Source License 1.1.

About

RDPAudit 2.0: Windows service plus WinForms configurator that collects RDP logon events, applies 21 alert rules, blocks brute-force IPs automatically and keeps SQLite WAL history.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages