Files
rdp-login-notifier/rdp-access-notification.ps1

226 lines
7.0 KiB
PowerShell

# Script Name: rdp-access-notification.ps1
# Beschreibung: Versendet Benachrichtigungen (E-Mail / Ntfy) bei RDP-Anmeldung
# Autor: Patrick Asmus
# Web: https://www.patrick-asmus.de
# Git-Reposit.: https://git.techniverse.net/scriptos/rdp-access-mailbenachrichtigung.git
# Version: 4.0
# Datum: 26.04.2026
# Modifikation: Zusammenfuehrung AD/Local, Config-Datei, Ntfy-Support
#####################################################
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$configPath = Join-Path $scriptDir "config.conf"
if (-not (Test-Path $configPath)) {
Write-Error "Konfigurationsdatei nicht gefunden: $configPath"
exit 1
}
# --- Config parsen ---
$conf = @{}
foreach ($line in Get-Content -Path $configPath) {
$line = $line.Trim()
if ($line -eq "" -or $line.StartsWith("#")) { continue }
$parts = $line -split "=", 2
if ($parts.Count -eq 2) {
$conf[$parts[0].Trim()] = $parts[1].Trim()
}
}
# --- Funktionen ---
function Send-Email {
param(
[string]$To,
[string]$RecipientName,
[string]$Subject,
[string]$ComputerName,
[string]$EventDate,
[string]$EventTime,
[string]$Domain,
[string]$User,
[string]$ClientIP
)
$htmlBody = @"
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
<style>
body { font-family: Segoe UI, Tahoma, Geneva, Verdana, sans-serif; color: #333; margin: 0; padding: 0; background-color: #f4f4f4; }
.container { max-width: 600px; margin: 20px auto; background: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
.header { background: #2c3e50; color: #ffffff; padding: 20px 30px; font-size: 18px; font-weight: 600; }
.content { padding: 25px 30px; line-height: 1.6; }
.info-table { width: 100%; border-collapse: collapse; margin-top: 15px; }
.info-table td { padding: 8px 12px; border-bottom: 1px solid #eee; }
.info-table td:first-child { font-weight: 600; white-space: nowrap; width: 180px; color: #555; }
.footer { background: #f8f8f8; padding: 15px 30px; font-size: 12px; color: #999; text-align: center; border-top: 1px solid #eee; }
</style>
</head>
<body>
<div class="container">
<div class="header">RDP-Zugriff erkannt</div>
<div class="content">
<p>Hallo <strong>$RecipientName</strong>,</p>
<p>auf der Windows-Maschine <strong>$ComputerName</strong> wurde eine RDP-Anmeldung registriert.</p>
<table class="info-table">
<tr><td>Datum</td><td>$EventDate</td></tr>
<tr><td>Uhrzeit</td><td>$EventTime</td></tr>
<tr><td>Dom&auml;ne</td><td>$Domain</td></tr>
<tr><td>Benutzer</td><td>$User</td></tr>
<tr><td>IP-Adresse des Clients</td><td>$ClientIP</td></tr>
</table>
</div>
<div class="footer">Diese Nachricht wurde automatisch generiert.</div>
</div>
</body>
</html>
"@
if (-not $To) {
Write-Warning "Kein Empfaenger fuer E-Mail (Name: $RecipientName) - uebersprungen"
return
}
try {
Send-MailMessage `
-SmtpServer $conf["SMTP_SERVER"] `
-From "$($conf["SMTP_FROM_NAME"]) <$($conf["SMTP_FROM_EMAIL"])>" `
-To $To `
-Subject $Subject `
-Body $htmlBody `
-BodyAsHtml `
-Encoding ([System.Text.Encoding]::UTF8) `
-ErrorAction Stop
}
catch {
Write-Error "E-Mail an $To fehlgeschlagen: $_"
}
}
function Send-Ntfy {
param(
[string]$Title,
[string]$Message
)
$ntfyUrl = "$($conf["NTFY_SERVER"])/$($conf["NTFY_TOPIC"])"
$headers = @{
"Title" = $Title
"Priority" = $conf["NTFY_PRIORITY"]
"Tags" = $conf["NTFY_TAGS"]
}
if ($conf["NTFY_AUTH_TOKEN"]) {
$headers["Authorization"] = "Bearer $($conf["NTFY_AUTH_TOKEN"])"
}
try {
Invoke-RestMethod `
-Uri $ntfyUrl `
-Method Post `
-Headers $headers `
-Body ([System.Text.Encoding]::UTF8.GetBytes($Message)) `
-ContentType "text/plain; charset=utf-8"
}
catch {
Write-Error "Ntfy-Benachrichtigung fehlgeschlagen: $_"
}
}
# --- RDP-Event auslesen ---
$eventID = 1149
$eventLogName = "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational"
$latestEvent = Get-WinEvent -LogName $eventLogName -FilterXPath "<QueryList><Query Id='0' Path='$eventLogName'><Select Path='$eventLogName'>*[System[(EventID=$eventID)]]</Select></Query></QueryList>" | Select-Object -First 1
if (-not $latestEvent) {
exit 0
}
$xml = [xml]$latestEvent.ToXml()
if (-not $xml.Event.UserData) {
exit 0
}
$user = $xml.Event.UserData.EventXML.Param1
$domain = $xml.Event.UserData.EventXML.Param2
$clientIP = $xml.Event.UserData.EventXML.Param3
$eventTime = $latestEvent.TimeCreated
$computerName = $latestEvent.MachineName
$eventDate = $eventTime.ToString('dd.MM.yyyy')
$eventTimeStr = $eventTime.ToString('HH:mm:ss')
$subject = "RDP-Anmeldung auf $computerName registriert"
# --- Empfaenger ermitteln ---
$recipients = @()
switch ($conf["MODE"]) {
"ad" {
$adMembers = Get-ADGroupMember -Identity $conf["AD_SECURITY_GROUP_DN"] | Where-Object { $_.objectClass -eq "user" }
foreach ($member in $adMembers) {
$adUser = Get-ADUser $member.DistinguishedName -Properties GivenName, Surname, EmailAddress
$recipients += [PSCustomObject]@{
Name = "$($adUser.GivenName) $($adUser.Surname)"
Email = $adUser.EmailAddress
}
}
}
"local" {
foreach ($entry in $conf["LOCAL_RECIPIENTS"] -split ";") {
$entry = $entry.Trim()
if ($entry -eq "") { continue }
$parts = $entry -split ",", 2
if ($parts.Count -eq 2) {
$recipients += [PSCustomObject]@{
Name = $parts[0].Trim()
Email = $parts[1].Trim()
}
}
}
}
default {
Write-Error "Unbekannter Modus: $($conf["MODE"]). Erlaubt: 'ad', 'local'"
exit 1
}
}
# --- Benachrichtigungen versenden ---
$methods = $conf["NOTIFICATION_METHODS"] -split ","
if ($methods.Trim() -contains "email") {
foreach ($recipient in $recipients) {
Send-Email `
-To $recipient.Email `
-RecipientName $recipient.Name `
-Subject $subject `
-ComputerName $computerName `
-EventDate $eventDate `
-EventTime $eventTimeStr `
-Domain $domain `
-User $user `
-ClientIP $clientIP
}
}
if ($methods.Trim() -contains "ntfy") {
$ntfyMessage = @"
Maschine: $computerName
Datum: $eventDate
Uhrzeit: $eventTimeStr
Domaene: $domain
Benutzer: $user
Client-IP: $clientIP
"@
Send-Ntfy -Title $subject -Message $ntfyMessage
}