Extra Systems Ban Software (ESBANS)

ES-RDP

Module rdp-run

The rdp-run module of our original Windows remote desktop security system consists of two files: the core PowerShell script rdp-run.ps1 (which identifies and blocks unauthorized connection attempts) and a helper file rdp-run.bat (which is called from Windows Task Scheduler every 10 minutes and runs the main rdp-run.ps1 file).

The rdp-run.bat file looks like this on our system:

powershell.exe -File "C:\Scripts\rdp-run.ps1"

Be sure to replace "C:\Scripts" with the actual path to your installation directory. The primary script, rdp-run.ps1, contains the following logic:

. "$PSScriptRoot\common.ps1"

# 2. RETRIEVING VIOLATIONS (Iterating through ban rules)
$RawOffenders = @()

foreach ($Rule in $BanRules) {
    $StartTime = (Get-Date).AddHours(-$Rule.Hours)
    $Events = Get-WinEvent -FilterHashtable @{LogName=$LogName; ID=$Rule.ID; StartTime=$StartTime} -ErrorAction SilentlyContinue
    
    if ($Events) {
        $List = $Events | ForEach-Object {
            if ($_.Message -match "(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})") {
                $FoundIP = $Matches[1]

                # CHECKING AGAINST WHITELIST
                $IsWhite = $false
                foreach ($WhiteIP in $WhiteList) {
                    if ($FoundIP -like $WhiteIP) { 
                        $IsWhite = $true
                        break 
                    }
                }

                if (-not $IsWhite) { 
                    [PSCustomObject]@{ IP = $FoundIP; Type = $Rule.Type }
                }

            }
        } | Group-Object IP | Where-Object { $_.Count -ge $Rule.Limit }
        
        if ($List) { $RawOffenders += $List }
    }
}

# Merge and collapse duplicates
$Offenders = $RawOffenders | Group-Object Name | ForEach-Object { $_.Group[0] }

# 3. BAN NEW OFFENDERS
if ($Offenders) {
    $CurDate = Get-Date -Format "yyyy-MM-dd"
    foreach ($Offender in $Offenders) {
        $IP = $Offender.Name
        $Type = $Offender.Group[0].Type
	$FirewallPrefix = $FirewallPrefixes['short']
        $TechnicalName = $FirewallPrefix + $IP.Replace('.', '_')
        if (-not (Get-NetFirewallRule -Name $TechnicalName -ErrorAction SilentlyContinue)) {
		$Description = "Type: $Type. Attempts: $($Offender.Count). Created: $(Get-Date)"
		New-NetFirewallRule -Name $TechnicalName -DisplayName "$FirewallPrefix$CurDate`_$IP" -Direction Inbound -Action Block -RemoteAddress $IP -Description $Description | Out-Null
		# --- NEW BLOCK FOR DB ---
		# Calculate subnet: extract everything up to the last octet and append .0
		$Subnet = $IP.Substring(0, $IP.LastIndexOf('.')) + ".0"
		# The SQL query saves both the IP and its subnet
		$LogQuery = "INSERT INTO ban_log (ban_addr, ban_subnet) VALUES (INET_ATON('$IP'), INET_ATON('$Subnet'));"
		# Execute the database query
		& $mysql_path --user=$mysql_user --password=$mysql_password --database=$mysql_dbName --execute="$LogQuery" 2>$null
		# -------------------------
            
        }
    }
}

As shown in the snippet above, this script relies on the general system settings from the file common.ps1, and also documents its activity in the ban_log table (this is necessary for the operation of other modules whose task is secondary banning - repeat offenders, address blocks, etc.).

The content of this page is also available in Russian.


© Extra Systems, 2026 Extra Web Top