Using PowerShell To Maintain Windows Firewall Rules For Remote Access


Editor's note: The following post was written by Visual Studio and Development Technologies MVP Terri Donahue as part of our Technical Tuesday series. Albert Duan of the MVP Award Blog Technical Committee served as the technical reviewer for this piece.

As System Administrators, how many times have we checked our event viewer logs to see tons of access attempts against commonly open application ports like RDP, FTP, and SQL? Sometimes these attempts are successful, but even when access is not gained, the application can be compromised due to resource constraints and other issues created by this scenario.

Because of this occurrence, I decided to implement an automated Firewall management process. I have many standalone machines that I provide primary system administration support for. This requires a unique solution, which provides automated updates with the ability to add/remove/update IPs to gain access to the required resource in a timely fashion. I focused on RDP, FTP, and SQL access. This script could easily be modified to include remote PowerShell or IIS administration access.

There are 3 main pieces to this implementation: a scheduled task, a web page, and of course, the PowerShell script. I’ll provide the settings that I use for the scheduled task, but this can be modified to meet your requirements. I’ll also provide the format for the web page and a link to download the PowerShell script from the TechNet gallery.

There is some prep work required for the user running this process. For starters, create a unique username, set a very strong password and enable the ‘password never expires’ flag.

New user dialog

This user will be the identity that is leveraged to run the scheduled task. It needs to be a member of the Network Configuration Operators group as well as have the Log on as a batch job security setting applied. This policy is found within Local Policies/User Rights Assignment.

Group assignment

Another important factor is to host the web page in a single location to which all servers have access. I use a page configured in our CMS to host the data that is consumed by the PowerShell script to define the firewall rules. The file should contain text that can be used to verify that the data has been download successfully. I learned this the hard way and temporarily locked myself and my colleagues out of our servers. You could also modify the script to use FTP rather than HTTP to grab the file.

For this post, I created a very simple html page that contains the comma separated values that will define the firewall rules. Here is a screenshot of what the file should contain:

iplist.html

Before you can setup the scheduled task, you need to acquire the PowerShell script. You can either copy the script directly from this post or download from here. Save this script to your script folder. I place all scripts in c:\admin\scripts.

Lastly, a scheduled task must to be setup. Create a task that runs as the user created earlier. I set the task to run every 5 minutes, but this can be adjusted per your needs. The program to run is PowerShell and the argument is the Maintain-FirewallRules.ps1 script. Include -verb runas at the end of the script name. It should be set as scriptlocation/scriptname -verb runas. The ‘-verb runas’ portion runs the script with elevated privileges. For detailed steps, you can view this video here

It is now time to run the script and verify that the new rules are created as expected. You can verify the rules are created and in use by checking the Firewall Monitoring MMC.

Windows Defender Firewall MMC

Once you have ensured that the new rules are in place and configured correctly, you will need to disable the existing open access rules for FTP, RDP, and SQL (or the protocols that you specified in the web page).

$rulelist = 'c:\admin\scripts\rulelist.txt'
$URI = 'http://localhost/iplist.html'
#URI = the web location of the IP list
 
$html = Invoke-WebRequest -Uri $URI -UseBasicParsing
$data = $html.Content | Out-File $rulelist
 
$ErrorActionPreference = 'SilentlyContinue'
 
 
Get-Content $rulelist |
ForEach-Object -Process {
$line = $_.TrimEnd()
if ($line.Contains('Format for entries')) { #used to ensure that file isn't blank
 
Get-NetFirewallRule -DisplayName Custom* | Remove-NetFirewallRule #delete existing rules created by script
 
}
$regex = '^([^|]*),([^|]*),([^|]*)'
#matches line as follows - IP,UserName,Protocol
#127.0.0.1,Terri,RDP
 
if ($line -match $regex) {
$name = $line.Split(',')[0]
$ip = $line.Split(',')[1]
$protocol = $line.Split(',')[2]
$ruleName = 'Custom-' + $protocol + '-' + $name
$description = 'Allow rule for ' + $protocol + ' access'
if ($protocol -eq 'RDP') {
$port = '3389'
}
elseif ($protocol -eq 'FTP') {
$port = @('21','4901-4910')
}
else {
$port = '1433'
}
 
 
'creating rule for ' + $protocol |Out-File $log -Append
 
New-NetFirewallRule -DisplayName $rulename -Description $description -RemoteAddress $ip -LocalPort $port -Protocol 'TCP' -Action 'Allow' -Enabled 'True'
 
}
} 

In conclusion, being able to programmatically control Windows Firewall rules remotely has proven to be a big win for me and the team that I support. IPs can be quickly added to restore connectivity if you are traveling and need to access a server from a different location or even if your dynamic home IP changes. This extra line of security has also greatly decreased the daily brute force attacks against these normally open protocols.  


Terri Donahue is a Microsoft MVP for IIS from North Carolina by way of Louisiana, Texas, and South Carolina. Terri is a she-geek who truly enjoys providing information and support related to many different technologies. She has worked in a Systems Administration role specifically dealing with IIS and Windows server since 1999. In her previous life, Terri has provided System Administration in both the corporate world and as a consultant for other technologies. You can reach Terri via Twitter @terrid_dw 

Comments (0)

Skip to main content