A guide on how to change the RDP port and firewall rules can be found here: http://www.iteezy.com/change-rdp-3389-port-on-windows-2008-server/qc/10098
Commercial tools for preventing RDP attacks also exists, like RdpGuard or Syspeace. Lately, a free alternative named EvlWatcher has been released.
I wanted to take a different approach. In Windows Server 2008 you can attach tasks to be executed on particular logged events. Adding an attacking IP to the Windows firewall is actually an easy task. I had Windows execute this script whenever event ID 4625 occured:
fail2ban.vbs:
- If wscript.arguments.count = 2 then
- Dim firewall, rule, rulename, ip, re, account
- 'Change this value! This rule must already exist in your inbound firewall rules
- rulename = "Fail2Ban"
- account = wscript.arguments.item(0)
- ip = wscript.arguments.item(1)
- 'MsgBox "Debug message: Invalid login with account " & account & " from IP " & ip
- Set re = new regexp
- re.Pattern = "\b(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\b"
- If re.Test(ip) And Not IsException(account, ip) Then
- Set firewall = CreateObject("HNetCfg.FwPolicy2")
- Set rule = firewall.Rules.Item(rulename)
- If Not (rule Is Nothing) Then
- If InStr(1,rule.RemoteAddresses,ip,1) = 0 Then
- rule.RemoteAddresses = rule.RemoteAddresses & "," & ip
- End If
- End If
- Set firewall = Nothing
- Else
- 'Invalid IP or excemption from rule
- End If
- end If
- 'Handle exception cases here, you don't want to ban your own IP, for instance...Customize to your needs
- Function IsException(account, ip)
- Dim exip
- exip = "My.IP"
- IsException = False
- If ip = exip Then
- IsException = True
- End If
- End Function
For creating the script above I used this blog for inspiration.
For creating the event based task I used this blog for reference. Essential parts of the task xml configuration I changed to fit my needs:
- <Triggers>
- <EventTrigger>
- <Enabled>true</Enabled>
- <Subscription>...omitted for layout purposes...</Subscription>
- <ValueQueries>
- <Value name="AccountDomain">Event/EventData/Data[@Name='TargetDomainName']</Value>
- <Value name="AccountName">Event/EventData/Data[@Name='TargetUserName']</Value>
- <Value name="ClientAddress">Event/EventData/Data[@Name='IpAddress']</Value>
- <Value name="Computer">Event/System/Computer</Value>
- <Value name="EventID">Event/System/EventID</Value>
- </ValueQueries>
- </EventTrigger>
- </Triggers>
- ...
- <Actions Context="Author">
- <Exec>
- <Command>D:\Scripts\fail2ban.vbs</Command>
- <Arguments>"$(AccountName)" "$(ClientAddress)"</Arguments>
- </Exec>
- </Actions>
Fail2Ban.vbs:
- Dim objShell, scriptpath, args, ip, acc
- scriptpath = "D:\Scripts\fail2ban.ps1"
- acc = wscript.arguments.item(0)
- ip = wscript.arguments.item(1)
- args = chr(34) & acc & chr(34) & " " & chr(34) & ip & chr(34)
- Set objShell = CreateObject("WScript.Shell")
- 'Run powershell hidden
- objShell.Run ("powershell " & scriptpath & " " & args), 0, true
- Set objShell = Nothing
- $targetaccount = $args[0]
- $sourceip = $args[1]
- #Filter/Threshold options
- $datefilter = [DateTime]::Now.AddHours(-1) # check only last x hours
- $countfilter = 3
- $rulename ="MyRule" #Firewall rule name
- $TargetUserName = @{n='TargetUserName';e={$_.ReplacementStrings[5]}}
- $IpAddress = @{n='IpAddress';e={$_.ReplacementStrings[19]}}
- #return IP if number of failed logins for specifed IP has exceeded x tries within specified timeframe
- $IP2Ban = Get-Eventlog security -InstanceId 4625 -After $datefilter | where {$_.ReplacementStrings[19] -eq $sourceip} | select-object $IpAddress | Group-Object -Property IPAddress | where Count -gt $countfilter | Select-Object -Property Name
- if ( $IP2Ban -ne $null)
- {
- #Add IP to firewall
- #$IP2Ban.Name is same as $sourceip
- $fw = New-object –comObject HNetCfg.FwPolicy2
- $myrule = $fw.Rules | where {$_.Name -eq $rulename}
- if (-not ($myrule.RemoteAddresses -match $sourceip) -and -not ($sourceip -like "my.ip"))
- {
- $myrule.RemoteAddresses += (","+$sourceip)
- }
- $fw = $null
- }