可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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
回答1:
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.
回答2:
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"}
回答3:
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" }
回答4:
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()' ..
回答5:
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.
回答6:
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>>