Sync all scripts from website downloads — 352 scripts total

Includes updated JS challenge scripts with Claude-User whitelist,
same-site referer bypass, Blackbox-Exporter allowed bot, and all
new exporters, cheat sheets, and automation scripts.
This commit is contained in:
2026-05-25 03:31:08 +02:00
parent dbd6bf0324
commit a1a17e81a1
332 changed files with 174509 additions and 1106 deletions
+334
View File
@@ -0,0 +1,334 @@
<#
.SYNOPSIS
Windows Remote Desktop Services Prometheus Metrics Exporter
.DESCRIPTION
Prometheus exporter for Windows RDS. Monitors active/disconnected sessions,
per-user session details, license availability, session host resources,
Connection Broker status, and RD Gateway metrics.
.PARAMETER TextFile
Write to windows_exporter textfile directory
.PARAMETER OutFile
Write metrics to a specific file path
.PARAMETER Install
Create a scheduled task for automatic collection
.PARAMETER Listen
Start HTTP listener on specified address:port
.PARAMETER Interval
Collection interval in seconds for scheduled task (default: 120)
.NOTES
Author: Phil Connor
Contact: contact@mylinux.work
Website: https://mylinux.work
License: MIT
Version: 1.0
#>
param(
[switch]$TextFile,
[string]$OutFile = "",
[switch]$Install,
[string]$Listen = "",
[int]$Interval = 120
)
$ErrorActionPreference = "SilentlyContinue"
$Version = "1.0"
$TextfileDir = "C:\ProgramData\node_exporter"
$MetricPrefix = "rds"
# ============================================================================
# HELPER FUNCTIONS
# ============================================================================
function Get-PrometheusEscape {
param([string]$Value)
$Value -replace '\\', '\\' -replace '"', '\"' -replace "`n", ''
}
function Write-MetricHeader {
param([string]$Name, [string]$Help, [string]$Type)
"# HELP $Name $Help"
"# TYPE $Name $Type"
}
# ============================================================================
# METRIC GENERATION
# ============================================================================
function Get-RdsMetrics {
$startTime = Get-Date
$metrics = [System.Collections.ArrayList]::new()
# Check if RDS module is available
$rdsAvailable = $false
if (Get-Module -ListAvailable -Name "RemoteDesktop" -ErrorAction SilentlyContinue) {
Import-Module RemoteDesktop -ErrorAction SilentlyContinue
$rdsAvailable = $true
}
$up = if ($rdsAvailable) { 1 } else { 0 }
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_up" "RDS exporter status (1=up, 0=down)" "gauge"))
[void]$metrics.Add("${MetricPrefix}_up $up")
[void]$metrics.Add("")
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_exporter_info" "Exporter version information" "gauge"))
[void]$metrics.Add("${MetricPrefix}_exporter_info{version=`"$Version`"} 1")
[void]$metrics.Add("")
if ($up -eq 0) {
$endTime = Get-Date
$duration = [math]::Round(($endTime - $startTime).TotalSeconds, 2)
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_exporter_duration_seconds" "Script execution time" "gauge"))
[void]$metrics.Add("${MetricPrefix}_exporter_duration_seconds $duration")
return ($metrics -join "`n")
}
# ========================================================================
# SESSION METRICS
# ========================================================================
try {
$sessions = Get-RDUserSession -ErrorAction Stop
$sessionHosts = $sessions | Group-Object -Property HostServer
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_sessions_active" "Active RDS sessions per host" "gauge"))
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_sessions_disconnected" "Disconnected RDS sessions per host" "gauge"))
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_sessions_total" "Total RDS sessions per host" "gauge"))
$totalActive = 0
$totalDisconnected = 0
foreach ($hostGroup in $sessionHosts) {
$host = Get-PrometheusEscape $hostGroup.Name
$active = @($hostGroup.Group | Where-Object { $_.SessionState -eq "STATE_ACTIVE" }).Count
$disconnected = @($hostGroup.Group | Where-Object { $_.SessionState -eq "STATE_DISCONNECTED" }).Count
$total = $hostGroup.Count
[void]$metrics.Add("${MetricPrefix}_sessions_active{host=`"$host`"} $active")
[void]$metrics.Add("${MetricPrefix}_sessions_disconnected{host=`"$host`"} $disconnected")
[void]$metrics.Add("${MetricPrefix}_sessions_total{host=`"$host`"} $total")
$totalActive += $active
$totalDisconnected += $disconnected
}
[void]$metrics.Add("")
# Per-user session details
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_session_state" "Per-user session state (1=current)" "gauge"))
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_session_idle_seconds" "Session idle time in seconds" "gauge"))
foreach ($session in $sessions) {
$host = Get-PrometheusEscape $session.HostServer
$user = Get-PrometheusEscape $session.UserName
$state = $session.SessionState -replace "STATE_", ""
[void]$metrics.Add("${MetricPrefix}_session_state{host=`"$host`",user=`"$user`",state=`"$state`"} 1")
if ($session.IdleTime) {
$idleSeconds = [math]::Round($session.IdleTime.TotalSeconds)
[void]$metrics.Add("${MetricPrefix}_session_idle_seconds{host=`"$host`",user=`"$user`"} $idleSeconds")
}
}
[void]$metrics.Add("")
} catch {
[void]$metrics.Add("# INFO: Could not query RDS sessions: $_")
[void]$metrics.Add("")
}
# ========================================================================
# LICENSE METRICS
# ========================================================================
try {
$licenseServers = Get-RDLicenseConfiguration -ErrorAction Stop
if ($licenseServers) {
$licenses = Get-WmiObject -Class Win32_TSLicenseKeyPack -ErrorAction Stop
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_license_total" "Total RDS licenses by type" "gauge"))
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_license_available" "Available RDS licenses by type" "gauge"))
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_license_used" "Used RDS licenses by type" "gauge"))
foreach ($lic in $licenses) {
$type = switch ($lic.ProductVersionID) {
0 { "PerDevice" }
1 { "PerUser" }
2 { "PerDevice" }
default { "Unknown" }
}
$total = $lic.TotalLicenses
$available = $lic.AvailableLicenses
$used = $total - $available
[void]$metrics.Add("${MetricPrefix}_license_total{type=`"$type`"} $total")
[void]$metrics.Add("${MetricPrefix}_license_available{type=`"$type`"} $available")
[void]$metrics.Add("${MetricPrefix}_license_used{type=`"$type`"} $used")
}
[void]$metrics.Add("")
}
} catch {
# License server may not be on this host
}
# ========================================================================
# SESSION HOST RESOURCE METRICS
# ========================================================================
try {
$rdServers = Get-RDServer -Role "RDS-RD-SERVER" -ErrorAction Stop
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_host_cpu_percent" "Session host CPU usage" "gauge"))
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_host_memory_percent" "Session host memory usage" "gauge"))
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_host_disk_free_bytes" "Session host free disk space" "gauge"))
foreach ($server in $rdServers) {
$hostName = Get-PrometheusEscape $server.Server
$cpu = Get-Counter -ComputerName $server.Server -Counter "\Processor(_Total)\% Processor Time" -ErrorAction SilentlyContinue
if ($cpu) {
$cpuVal = [math]::Round($cpu.CounterSamples[0].CookedValue, 1)
[void]$metrics.Add("${MetricPrefix}_host_cpu_percent{host=`"$hostName`"} $cpuVal")
}
$mem = Get-WmiObject -ComputerName $server.Server -Class Win32_OperatingSystem -ErrorAction SilentlyContinue
if ($mem) {
$memPercent = [math]::Round((($mem.TotalVisibleMemorySize - $mem.FreePhysicalMemory) / $mem.TotalVisibleMemorySize) * 100, 1)
[void]$metrics.Add("${MetricPrefix}_host_memory_percent{host=`"$hostName`"} $memPercent")
}
$disks = Get-WmiObject -ComputerName $server.Server -Class Win32_LogicalDisk -Filter "DriveType=3" -ErrorAction SilentlyContinue
foreach ($disk in $disks) {
$drive = $disk.DeviceID -replace ":", ""
[void]$metrics.Add("${MetricPrefix}_host_disk_free_bytes{host=`"$hostName`",drive=`"$drive`"} $($disk.FreeSpace)")
}
}
[void]$metrics.Add("")
} catch {
# May not have access to remote servers
}
# ========================================================================
# CONNECTION BROKER
# ========================================================================
$brokerSvc = Get-Service -Name "Tssdis" -ErrorAction SilentlyContinue
$brokerUp = if ($brokerSvc -and $brokerSvc.Status -eq "Running") { 1 } else { 0 }
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_connection_broker_up" "Connection Broker service status" "gauge"))
[void]$metrics.Add("${MetricPrefix}_connection_broker_up $brokerUp")
[void]$metrics.Add("")
# Collection health
try {
$collections = Get-RDSessionCollection -ErrorAction Stop
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_collection_health" "Collection health (1=healthy)" "gauge"))
foreach ($col in $collections) {
$colName = Get-PrometheusEscape $col.CollectionName
$health = 1
[void]$metrics.Add("${MetricPrefix}_collection_health{collection=`"$colName`"} $health")
}
[void]$metrics.Add("")
} catch {
# Collections may not be configured
}
# ========================================================================
# RD GATEWAY METRICS
# ========================================================================
try {
$gwCounter = Get-Counter -Counter "\TS Gateway\Current Connections" -ErrorAction Stop
if ($gwCounter) {
$gwActive = [math]::Round($gwCounter.CounterSamples[0].CookedValue)
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_gateway_connections_active" "Active RD Gateway connections" "gauge"))
[void]$metrics.Add("${MetricPrefix}_gateway_connections_active $gwActive")
[void]$metrics.Add("")
}
$gwRate = Get-Counter -Counter "\TS Gateway\Connections/Sec" -ErrorAction SilentlyContinue
if ($gwRate) {
$gwPerSec = [math]::Round($gwRate.CounterSamples[0].CookedValue, 2)
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_gateway_connections_per_second" "RD Gateway connection rate" "gauge"))
[void]$metrics.Add("${MetricPrefix}_gateway_connections_per_second $gwPerSec")
[void]$metrics.Add("")
}
$gwAuth = Get-Counter -Counter "\TS Gateway\Failed Authentications" -ErrorAction SilentlyContinue
if ($gwAuth) {
$gwFailed = [math]::Round($gwAuth.CounterSamples[0].CookedValue)
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_gateway_auth_failures_total" "RD Gateway authentication failures" "counter"))
[void]$metrics.Add("${MetricPrefix}_gateway_auth_failures_total $gwFailed")
[void]$metrics.Add("")
}
} catch {
# Gateway may not be installed
}
# ========================================================================
# EXPORTER RUNTIME
# ========================================================================
$endTime = Get-Date
$duration = [math]::Round(($endTime - $startTime).TotalSeconds, 2)
$timestamp = [math]::Round((Get-Date -UFormat %s), 0)
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_exporter_duration_seconds" "Script execution time" "gauge"))
[void]$metrics.Add("${MetricPrefix}_exporter_duration_seconds $duration")
[void]$metrics.Add("")
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_exporter_last_run_timestamp" "Unix timestamp of last run" "gauge"))
[void]$metrics.Add("${MetricPrefix}_exporter_last_run_timestamp $timestamp")
return ($metrics -join "`n")
}
# ============================================================================
# OUTPUT MODES
# ============================================================================
if ($Install) {
$scriptPath = $MyInvocation.MyCommand.Path
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -TextFile"
$trigger = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Seconds $Interval) -Once -At (Get-Date)
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable
Register-ScheduledTask -TaskName "RDS Metrics Exporter" -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force
Write-Host "Scheduled task 'RDS Metrics Exporter' created (interval: ${Interval}s)"
exit 0
}
if ($Listen -ne "") {
$port = $Listen -replace '.*:', ''
if (-not $port) { $port = "9185" }
$listener = [System.Net.HttpListener]::new()
$listener.Prefixes.Add("http://+:$port/")
$listener.Start()
Write-Host "RDS exporter listening on port $port..."
while ($listener.IsListening) {
$context = $listener.GetContext()
$response = $context.Response
$output = Get-RdsMetrics
$buffer = [System.Text.Encoding]::UTF8.GetBytes($output)
$response.ContentType = "text/plain; version=0.0.4"
$response.ContentLength64 = $buffer.Length
$response.OutputStream.Write($buffer, 0, $buffer.Length)
$response.Close()
}
} elseif ($TextFile -or $OutFile -ne "") {
$outputPath = if ($OutFile -ne "") { $OutFile } else { Join-Path $TextfileDir "rds.prom" }
$outputDir = Split-Path $outputPath -Parent
if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir -Force | Out-Null }
$tempFile = Join-Path $outputDir ".rds-metrics.tmp"
$metricsOutput = Get-RdsMetrics
$metricsOutput | Out-File -FilePath $tempFile -Encoding utf8 -NoNewline
Move-Item -Path $tempFile -Destination $outputPath -Force
Write-Host "Metrics written to $outputPath"
} else {
Get-RdsMetrics
}