How can you check for existing firewall rules using Powershell
So, I've got this script:
function Add-FirewallRule {
param(
$name,
$tcpPorts,
$appName = $null,
$serviceName = $null
)
$fw = New-Object -ComObject hnetcfg.fwpolicy2
$rule = New-Object -ComObject HNetCfg.FWRule
$rule.Name = $name
if ($appName -ne $null) { $rule.ApplicationName = $appName }
if ($serviceName -ne $null) { $rule.serviceName = $serviceName }
$rule开发者_开发技巧.Protocol = 6 #NET_FW_IP_PROTOCOL_TCP
$rule.LocalPorts = $tcpPorts
$rule.Enabled = $true
$rule.Grouping = "@firewallapi.dll,-23255"
$rule.Profiles = 7 # all
$rule.Action = 1 # NET_FW_ACTION_ALLOW
$rule.EdgeTraversal = $false
if(*here*)
{
$fw.Rules.Add($rule)
}
}
and I want to be able to put something in the if() that will check and see if the rule already exists before it adds it. I'm not terribly familiar with powershell, so go easy on me :P
PowerShell Firewall example for SDL Microservices
Only create a new firewall rule if it does not already exist
$rules = Get-NetFirewallRule
$par = @{
DisplayName = ""
LocalPort = 80
Direction="Inbound"
Protocol ="TCP"
Action = "Allow"
}
$par.LocalPort = 8081
$par.DisplayName = "SDL Web 8 Stage Content Microservice on port $($par.LocalPort)"
if (-not $rules.DisplayName.Contains($par.DisplayName)) {New-NetFirewallRule @par}
$par.LocalPort = 8082
$par.DisplayName = "SDL Web 8 Stage Discovery Microservice on port $($par.LocalPort)"
if (-not $rules.DisplayName.Contains($par.DisplayName)) {New-NetFirewallRule @par"}
Why not just:
$r = Get-NetFirewallRule -DisplayName 'Docker Cluster Management Communications' 2> $null;
if ($r) {
write-host "found it";
}
else {
write-host "did not find it"
}
MSDN has some extensive documentation on the Windows Firewall API here:
http://msdn.microsoft.com/en-us/library/aa366449(v=vs.85).aspx
You'll want to start with instantiating the HNetCfg.FwMgr COM object -- this will give you access to query various existing rules via the HNetCfg.FwMgr.LocalPolicy.CurrentProfile.
There are several different types of rules: Authorized Applications, Globally Open Ports, ICMP settings, and "services." The INetFwProfile object (retrieved via the CurrentProfile) has properties that allow access to these rules.
http://msdn.microsoft.com/en-us/library/aa365327(v=vs.85).aspx
Update (2014-01-30): In Windows 8 and Windows Server 2012, there is a PowerShell module called NetSecurity
, which contains the Get-NetFirewallRule
command. You can use this command to discover which firewall rules are already defined. To add a new firewall rule, use the New-NetFirewallRule
command in the same NetSecurity
module.
This doesn't seem to be widely known. You can do a fast search of the firewall rules by going first to the filter commands, for example, to list the ones with 'chrome.exe' as the program. You can use a wildcard with -Program, even though it doesn't seem to be documented.
Get-NetFirewallApplicationFilter -Program *chrome.exe | Get-NetFirewallRule |
% Displayname
Google Chrome (mDNS-In)
Get-NetFirewallPortFilter | Where Localport -match 3389 | Get-NetFirewallRule |
% Displayname
Remote Desktop - User Mode (TCP-In)
Remote Desktop - User Mode (UDP-In)
This answer over on serverfault, which was based on this blog-post, might help:
Function Get-EnabledRules
{
Param($profile)
$rules = (New-Object -comObject HNetCfg.FwPolicy2).rules
$rules = $rules | where-object {$_.Enabled -eq $true}
$rules = $rules | where-object {$_.Profiles -bAND $profile}
$rules
}
$networkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"))
$connections = $networkListManager.GetNetworkConnections()
[int[] ] $connTypes = @()
$connTypes = ($connections | % {$_.GetNetwork().GetCategory()})
#$connTypes += 1
Write-Host $connTypes
$connTypes | ForEach-Object {Get-EnabledRules -profile $_ | sort localports,Protocol | format-table -wrap -autosize -property Name, @{Label="Action"; expression={$_.action}}, @{Label="Protocol"; expression={$_.protocol}}, localPorts,applicationname}
you will need to check the enabled rules in your 'if()' ..
You can do it in hacky way, so using Get-NetFirewallRule and surround it in try catch statement. If the rule doesn't exist, it will move us to catch statement so we can create a new rule there.
try {
$firewallRule = Get-NetFirewallRule -DisplayName PROGRAM -ErrorAction Stop
"Firewall rule already exist for program.exe" | Add-Content 'file.log'
}
catch {
if(-Not $firewallRule) {
New-NetFirewallRule -Program $ecfClient -Action Allow -Profile Any -DisplayName "PROGRAM"
"Firewall rule for ecfClient.exe succesffully created" | Add-Content 'file.log'
}
}
You can also check the value from the Get-NetFirewallRule, if the rule exists it will return true because variable isn't empty.
I know it's a dirty way for doing this, but when I was looking for the shortest way that really helped me.
Following up @Trevor Sullivian Suggestion here is test script which achieves the same using NetSecurity Module.
Import-Module NetSecurity
new-netfirewallrule -Action Allow -Direction Inbound -Enabled True -Protocol TCP -LocalPort <<Port>> -DisplayName <<Name>>
精彩评论