PowerShell 技能连载 - Windows 防火墙规则管理

适用于 PowerShell 5.1 及以上版本(Windows),需要管理员权限

Windows 防火墙是保障系统安全的第一道防线。在企业运维中,管理员经常需要批量查看、创建、修改或删除防火墙规则,以应对不同的网络环境和安全策略。手动通过 advfw.msc 图形界面操作不仅效率低下,而且难以保证多台机器之间的配置一致性。

PowerShell 提供了 NetSecurity 模块,其中包含一系列以 NetFirewall 开头的 cmdlet,可以方便地对防火墙规则、配置文件和地址进行程序化管理。结合脚本化思维,运维人员可以快速完成规则的批量审计与部署。

本文将从实际场景出发,演示如何用 PowerShell 查询现有防火墙规则、批量创建入站规则,以及导出规则审计报告。

查询防火墙规则

使用 Get-NetFirewallRule 可以列出系统中所有防火墙规则。配合 Get-NetFirewallAddressFilterGet-NetFirewallPortFilter 等关联 cmdlet,可以获取规则的详细信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查询所有已启用的入站规则,显示名称、方向、操作和配置文件
$rules = Get-NetFirewallRule |
Where-Object { $_.Enabled -eq $true -and $_.Direction -eq 'Inbound' } |
Sort-Object -Property DisplayName

foreach ($rule in $rules) {
$portFilter = $rule | Get-NetFirewallPortFilter -ErrorAction SilentlyContinue
$addressFilter = $rule | Get-NetFirewallAddressFilter -ErrorAction SilentlyContinue

[PSCustomObject]@{
Name = $rule.DisplayName
Direction = $rule.Direction
Action = $rule.Action
Profile = $rule.Profile
Protocol = if ($portFilter) { $portFilter.Protocol } else { 'N/A' }
LocalPort = if ($portFilter) { $portFilter.LocalPort -join ', ' } else { 'N/A' }
RemoteAddr = if ($addressFilter) { $addressFilter.RemoteAddress -join ', ' } else { 'N/A' }
}
}

执行结果示例:

1
2
3
4
5
6
Name                          Direction Action  Profile      Protocol LocalPort      RemoteAddr
---- --------- ------ ------- -------- --------- ----------
Core Networking - DHCP (In) Inbound Allow Any UDP 68, 546 LocalSubnet
Core Networking - IPv6 (In) Inbound Allow Any IPv6 N/A N/A
远程桌面 - 用户模式(TCP-In) Inbound Allow Private TCP 3389 Any
Windows 管理规范(WMI-In) Inbound Allow Domain TCP 0-65535 LocalSubnet

批量创建入站规则

在部署新服务时,通常需要为多个端口同时开放防火墙入站规则。下面的脚本演示如何根据配置表批量创建规则,并为每条规则添加描述和远程地址限制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 定义需要开放的端口规则列表
$firewallConfig = @(
@{
Name = 'Web Server - HTTP'
Port = 80
Protocol = 'TCP'
Profile = 'Any'
Description = '允许 HTTP 流量入站'
RemoteAddr = 'Any'
}
@{
Name = 'Web Server - HTTPS'
Port = 443
Protocol = 'TCP'
Profile = 'Any'
Description = '允许 HTTPS 流量入站'
RemoteAddr = 'Any'
}
@{
Name = 'Admin API'
Port = 8080
Protocol = 'TCP'
Profile = 'Private'
Description = '允许管理 API 访问,仅限内网'
RemoteAddr = '10.0.0.0/8'
}
)

foreach ($config in $firewallConfig) {
$existingRule = Get-NetFirewallRule -DisplayName $config.Name -ErrorAction SilentlyContinue

if ($existingRule) {
Write-Host "规则 '$($config.Name)' 已存在,跳过创建。" -ForegroundColor Yellow
continue
}

New-NetFirewallRule `
-DisplayName $config.Name `
-Direction Inbound `
-Action Allow `
-Protocol $config.Protocol `
-LocalPort $config.Port `
-Profile $config.Profile `
-RemoteAddress $config.RemoteAddr `
-Description $config.Description

Write-Host "已创建规则 '$($config.Name)' (端口 $($config.Port)/$($config.Protocol))" -ForegroundColor Green
}

执行结果示例:

1
2
3
已创建规则 'Web Server - HTTP' (端口 80/TCP)
已创建规则 'Web Server - HTTPS' (端口 443/TCP)
已创建规则 'Admin API' (端口 8080/TCP)

导出防火墙审计报告

定期的防火墙规则审计是安全合规的重要环节。以下脚本将所有防火墙规则导出为 CSV 文件,便于后续分析和归档。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 导出防火墙规则审计报告
$timestamp = Get-Date -Format 'yyyyMMdd_HHmmss'
$exportPath = Join-Path -Path $env:USERPROFILE -ChildPath "FirewallAudit_$timestamp.csv"

$allRules = Get-NetFirewallRule | Sort-Object -Property DisplayName

$report = foreach ($rule in $allRules) {
$portFilter = $rule | Get-NetFirewallPortFilter -ErrorAction SilentlyContinue
$addressFilter = $rule | Get-NetFirewallAddressFilter -ErrorAction SilentlyContinue
$appFilter = $rule | Get-NetFirewallApplicationFilter -ErrorAction SilentlyContinue

[PSCustomObject]@{
DisplayName = $rule.DisplayName
Group = $rule.Group
Enabled = $rule.Enabled
Direction = $rule.Direction
Action = $rule.Action
Profile = $rule.Profile
Protocol = if ($portFilter) { $portFilter.Protocol } else { '' }
LocalPort = if ($portFilter) { $portFilter.LocalPort -join '; ' } else { '' }
RemotePort = if ($portFilter) { $portFilter.RemotePort -join '; ' } else { '' }
LocalAddress = if ($addressFilter) { $addressFilter.LocalAddress -join '; ' } else { '' }
RemoteAddress = if ($addressFilter) { $addressFilter.RemoteAddress -join '; ' } else { '' }
Program = if ($appFilter) { $appFilter.Program } else { '' }
Description = $rule.Description
}
}

$report | Export-Csv -Path $exportPath -NoTypeInformation -Encoding UTF8

$totalCount = $report.Count
$enabledCount = ($report | Where-Object { $_.Enabled -eq $true }).Count
$allowCount = ($report | Where-Object { $_.Action -eq 'Allow' -and $_.Enabled -eq $true }).Count

Write-Host "审计报告已导出: $exportPath" -ForegroundColor Green
Write-Host "总规则数: $totalCount | 已启用: $enabledCount | 允许规则(已启用): $allowCount"

执行结果示例:

1
2
审计报告已导出: C:\Users\Admin\FirewallAudit_20250904_143022.csv
总规则数: 852 | 已启用: 356 | 允许规则(已启用): 214

禁用危险规则示例

在某些加固场景下,需要快速定位并禁用不符合安全策略的规则。例如,查找所有允许任意远程地址入站且已启用的 TCP 规则。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 查找并标记高风险入站规则
$highRiskRules = Get-NetFirewallRule |
Where-Object {
$_.Enabled -eq $true -and
$_.Direction -eq 'Inbound' -and
$_.Action -eq 'Allow'
}

$flagged = foreach ($rule in $highRiskRules) {
$addressFilter = $rule | Get-NetFirewallAddressFilter -ErrorAction SilentlyContinue
$portFilter = $rule | Get-NetFirewallPortFilter -ErrorAction SilentlyContinue

$remoteAddr = if ($addressFilter) { $addressFilter.RemoteAddress -join ', ' } else { '' }
$localPort = if ($portFilter) { $portFilter.LocalPort -join ', ' } else { '' }

# 标记远程地址为 Any 且端口开放的规则
if ($remoteAddr -eq 'Any' -and $localPort -ne '') {
[PSCustomObject]@{
Name = $rule.DisplayName
Profile = $rule.Profile
Protocol = $portFilter.Protocol
LocalPort = $localPort
RemoteAddr = $remoteAddr
Risk = 'High'
}
}
}

$flagged | Format-Table -AutoSize

Write-Host "`n共发现 $($flagged.Count) 条高风险规则,请逐一审核。" -ForegroundColor Red

执行结果示例:

1
2
3
4
5
6
7
Name                        Profile    Protocol LocalPort RemoteAddr Risk
---- ------- -------- --------- ---------- ----
Web Server - HTTP Any TCP 80 Any High
Web Server - HTTPS Any TCP 443 Any High
文件和打印机共享(回显请求) Private ICMPv4 * Any High

共发现 3 条高风险规则,请逐一审核。

注意事项

  1. 管理员权限:所有 NetFirewall 相关的 cmdlet 创建、修改和删除操作都需要以管理员身份运行 PowerShell,查询操作也建议在提升权限后执行以获取完整信息。

  2. 配置文件区分:Windows 防火墙有 Domain、Private、Public 三种配置文件,创建规则时务必根据实际网络环境选择正确的 Profile,避免在公用网络中暴露不必要的服务端口。

  3. 规则冲突检测:新创建规则前应先检查是否存在同名或相同端口/协议的规则,重复规则可能导致意外行为或排查困难。

  4. 远程地址最小化:生产环境中应遵循最小权限原则,将 RemoteAddress 尽量限定为特定 IP 段或子网,而非使用 Any,降低被攻击面。

  5. CSV 导出编码:导出包含中文规则名的 CSV 文件时,务必指定 -Encoding UTF8 参数,否则在 Excel 中打开可能出现乱码。

  6. 测试环境验证:批量修改防火墙规则前,建议先在测试环境或单台机器上验证效果,避免因规则配置不当导致服务不可达或远程管理中断。

PowerShell 技能连载 - Windows 防火墙规则管理

适用于 PowerShell 5.1 及以上版本(Windows 内置模块)

Windows 防火墙是服务器和终端安全的第一道防线。无论是部署新服务、排查网络故障还是进行安全加固,都离不开防火墙规则的配置与管理。传统的图形界面操作虽然直观,但在批量管理和自动化场景下效率低下,且容易遗漏。

PowerShell 内置的 NetSecurity 模块提供了完整的防火墙管理能力,支持查看、创建、修改和删除规则,所有操作都可以脚本化、可重复执行。对于运维工程师来说,掌握这套命令不仅能提高日常工作效率,更是实现基础设施即代码(IaC)的重要基础。

查看防火墙规则

日常运维中最常见的操作就是查看当前生效的防火墙规则。Get-NetFirewallRule 是核心命令,结合 Get-NetFirewallPortFilterGet-NetFirewallAddressFilter 可以获取完整的规则详情。

以下函数封装了常用的查询逻辑,支持按名称、方向、启用状态等条件过滤,并输出格式化的规则摘要:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function Get-FirewallRuleSummary {
param(
[string]$Name = "*",
[ValidateSet("Inbound", "Outbound", "Both")]
[string]$Direction = "Both",
[switch]$EnabledOnly
)

$filter = @{ DisplayName = $Name }
if ($Direction -ne "Both") {
$filter["Direction"] = $Direction
}
if ($EnabledOnly) {
$filter["Enabled"] = "True"
}

$rules = Get-NetFirewallRule @filter

$results = foreach ($rule in $rules) {
$portFilter = $rule | Get-NetFirewallPortFilter -ErrorAction SilentlyContinue
$addrFilter = $rule | Get-NetFirewallAddressFilter -ErrorAction SilentlyContinue

[PSCustomObject]@{
Name = $rule.DisplayName
Direction = $rule.Direction
Action = $rule.Action
Enabled = $rule.Enabled
Protocol = if ($portFilter) { $portFilter.Protocol } else { "Any" }
LocalPort = if ($portFilter) { $portFilter.LocalPort } else { "Any" }
RemoteAddr = if ($addrFilter) { $addrFilter.RemoteAddress } else { "Any" }
Profile = $rule.Profile
}
}

return $results | Sort-Object Enabled, Direction, Action
}

执行结果示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PS> Get-FirewallRuleSummary -Name "*SSH*" -EnabledOnly

Name : OpenSSH Server (sshd)
Direction : Inbound
Action : Allow
Enabled : True
Protocol : TCP
LocalPort : 22
RemoteAddr : Any
Profile : Any

Name : OpenSSH Client
Direction : Outbound
Action : Allow
Enabled : True
Protocol : TCP
LocalPort : Any
RemoteAddr : Any
Profile : Any

创建防火墙规则

创建规则是防火墙管理中最关键的操作。New-NetFirewallRule 命令支持丰富的参数,可以精确控制协议、端口、地址范围和配置文件。

以下函数将常见的规则创建流程封装为可复用的命令,内置了参数校验和冲突检测逻辑,避免重复创建同名规则:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
function New-FirewallAllowRule {
param(
[Parameter(Mandatory)]
[string]$Name,

[Parameter(Mandatory)]
[int]$Port,

[ValidateSet("TCP", "UDP")]
[string]$Protocol = "TCP",

[ValidateSet("Inbound", "Outbound")]
[string]$Direction = "Inbound",

[string[]]$RemoteAddress = "Any",

[ValidateSet("Domain", "Private", "Public", "Any")]
[string]$Profile = "Any"
)

# 检查同名规则是否已存在
$existing = Get-NetFirewallRule -DisplayName $Name -ErrorAction SilentlyContinue
if ($existing) {
Write-Warning "规则 '$Name' 已存在,跳过创建"
return $existing
}

$params = @{
DisplayName = $Name
Direction = $Direction
Action = "Allow"
Protocol = $Protocol
LocalPort = $Port
RemoteAddress = $RemoteAddress
Profile = $Profile
Enabled = "True"
}

$rule = New-NetFirewallRule @params
Write-Host "已创建规则: $Name ($Protocol/$Port, $Direction)"
return $rule
}

执行结果示例:

1
2
3
4
5
PS> New-FirewallAllowRule -Name "Web Server HTTP" -Port 80 -Protocol TCP
已创建规则: Web Server HTTP (TCP/80, Inbound)

PS> New-FirewallAllowRule -Name "Web Server HTTP" -Port 80
WARNING: 规则 'Web Server HTTP' 已存在,跳过创建

批量管理规则

在服务器初始化或安全加固场景中,往往需要一次性配置大量规则。手动逐条创建既繁琐又容易出错,批量管理脚本能显著提升效率和一致性。

以下函数接收规则定义数组,自动创建并输出执行报告,支持回滚操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
function Import-FirewallRuleSet {
param(
[Parameter(Mandatory)]
[string]$RuleSetName,

[Parameter(Mandatory)]
[array]$Rules
)

$report = @()
$created = @()

foreach ($rule in $Rules) {
$qualifiedName = "$RuleSetName - $($rule.Name)"
try {
$result = New-FirewallAllowRule `
-Name $qualifiedName `
-Port $rule.Port `
-Protocol $rule.Protocol `
-Direction $rule.Direction `
-RemoteAddress $rule.RemoteAddress `
-Profile $rule.Profile

if ($result) {
$created += $qualifiedName
$status = "Created"
}
else {
$status = "Skipped"
}
}
catch {
$status = "Error: $($_.Exception.Message)"
}

$report += [PSCustomObject]@{
Rule = $qualifiedName
Port = "$($rule.Protocol)/$($rule.Port)"
Status = $status
}
}

Write-Host "`n规则集 '$RuleSetName' 导入完成: $($created.Count)/$($Rules.Count) 条已创建"
return $report | Format-Table -AutoSize
}

使用示例——批量导入 Web 服务器所需规则:

1
2
3
4
5
6
7
$webRules = @(
@{ Name = "HTTP"; Port = 80; Protocol = "TCP"; Direction = "Inbound"; RemoteAddress = "Any"; Profile = "Any" }
@{ Name = "HTTPS"; Port = 443; Protocol = "TCP"; Direction = "Inbound"; RemoteAddress = "Any"; Profile = "Any" }
@{ Name = "SSH"; Port = 22; Protocol = "TCP"; Direction = "Inbound"; RemoteAddress = "10.0.0.0/8"; Profile = "Domain" }
)

Import-FirewallRuleSet -RuleSetName "Web Server" -Rules $webRules

执行结果示例:

1
2
3
4
5
6
7
8
9
10
11
已创建规则: Web Server - HTTP (TCP/80, Inbound)
已创建规则: Web Server - HTTPS (TCP/443, Inbound)
已创建规则: Web Server - SSH (TCP/22, Inbound)

规则集 'Web Server' 导入完成: 3/3 条已创建

Rule Port Status
---- ---- ------
Web Server - HTTP TCP/80 Created
Web Server - HTTPS TCP/443 Created
Web Server - SSH TCP/22 Created

导出与导入规则配置

在多台服务器之间同步防火墙配置,或者在变更前做备份,都需要导出导入功能。以下函数将规则集导出为 JSON 文件,便于版本控制和跨机器部署。

注意这里使用数组拼接 -join 来构建多行文本,避免在代码块中嵌入三反引号导致 Markdown 解析错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
function Export-FirewallRules {
param(
[Parameter(Mandatory)]
[string]$NamePattern,

[Parameter(Mandatory)]
[string]$OutputPath
)

$rules = Get-NetFirewallRule -DisplayName $NamePattern -ErrorAction SilentlyContinue

$export = foreach ($rule in $rules) {
$portFilter = $rule | Get-NetFirewallPortFilter -ErrorAction SilentlyContinue
$addrFilter = $rule | Get-NetFirewallAddressFilter -ErrorAction SilentlyContinue

@{
Name = $rule.DisplayName
Direction = [string]$rule.Direction
Action = [string]$rule.Action
Enabled = [string]$rule.Enabled
Protocol = if ($portFilter) { [string]$portFilter.Protocol } else { "" }
LocalPort = if ($portFilter) { [string]$portFilter.LocalPort } else { "" }
RemoteAddress = if ($addrFilter) { [string]$addrFilter.RemoteAddress } else { "" }
Profile = [string]$rule.Profile
}
}

$jsonLines = @(
"{"
' "ExportDate": "' + (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + '",'
' "RuleCount": ' + $export.Count + ','
' "Rules": ['
)

for ($i = 0; $i -lt $export.Count; $i++) {
$comma = if ($i -lt $export.Count - 1) { "," } else { "" }
$ruleJson = $export[$i] | ConvertTo-Json -Compress
$jsonLines += " $ruleJson$comma"
}

$jsonLines += @(
" ]"
"}"
)

($jsonLines -join "`n") | Out-File -FilePath $OutputPath -Encoding UTF8
Write-Host "已导出 $($export.Count) 条规则到: $OutputPath"
}

执行结果示例:

1
2
PS> Export-FirewallRules -NamePattern "Web Server*" -OutputPath "C:\Backup\firewall-web.json"
已导出 3 条规则到: C:\Backup\firewall-web.json

对应的导入函数从 JSON 文件读取规则定义并批量创建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function Import-FirewallRulesFromFile {
param(
[Parameter(Mandatory)]
[string]$FilePath
)

$content = Get-Content -Path $FilePath -Raw | ConvertFrom-Json
Write-Host "文件包含 $($content.RuleCount) 条规则,导出时间: $($content.ExportDate)"

$results = @()
foreach ($r in $content.Rules) {
try {
$existing = Get-NetFirewallRule -DisplayName $r.Name -ErrorAction SilentlyContinue
if ($existing) {
$results += [PSCustomObject]@{ Name = $r.Name; Status = "AlreadyExists" }
continue
}

New-NetFirewallRule `
-DisplayName $r.Name `
-Direction $r.Direction `
-Action $r.Action `
-Protocol $r.Protocol `
-LocalPort $r.LocalPort `
-RemoteAddress $r.RemoteAddress `
-Profile $r.Profile `
-Enabled $r.Enabled | Out-Null

$results += [PSCustomObject]@{ Name = $r.Name; Status = "Created" }
}
catch {
$results += [PSCustomObject]@{ Name = $r.Name; Status = "Error: $($_.Exception.Message)" }
}
}

$created = ($results | Where-Object Status -eq "Created").Count
Write-Host "`n导入完成: $created 条新建, $($results.Count - $created) 条跳过"
return $results | Format-Table -AutoSize
}

执行结果示例:

1
2
3
4
5
6
7
8
9
10
PS> Import-FirewallRulesFromFile -FilePath "C:\Backup\firewall-web.json"
文件包含 3 条规则,导出时间: 2025-04-16 10:30:00

导入完成: 3 条新建, 0 条跳过

Name Status
---- ------
Web Server - HTTP Created
Web Server - HTTPS Created
Web Server - SSH Created

服务器安全加固

生产服务器的防火墙配置直接决定攻击面大小。以下加固脚本针对常见的风险点实施最小权限原则:禁用所有入站流量后仅开放必要端口,限制管理端口的访问来源,并关闭不必要的出站流量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
function Initialize-ServerFirewallHardening {
param(
[int[]]$AllowedInboundPorts = @(80, 443),
[int]$SshPort = 22,
[string[]]$AdminNetworks = @("10.0.0.0/8", "172.16.0.0/12"),
[switch]$WhatIf
)

$log = @()

# 第一步:阻止所有默认入站流量
$step1 = "Step 1: 设置默认入站策略为阻止"
$log += $step1
Write-Host $step1

if (-not $WhatIf) {
Set-NetFirewallProfile -Profile Domain,Public,Private `
-DefaultInboundAction Block `
-DefaultOutboundAction Allow `
-Enabled True
}

# 第二步:开放业务端口
$step2 = "Step 2: 开放业务端口 ($($AllowedInboundPorts -join ', '))"
$log += $step2
Write-Host $step2

foreach ($port in $AllowedInboundPorts) {
$ruleName = "Hardened - HTTP/S Port $port"
if (-not $WhatIf) {
New-FirewallAllowRule -Name $ruleName -Port $port -Protocol TCP | Out-Null
}
$log += " -> 已开放端口: $port/TCP"
}

# 第三步:限制管理端口访问来源
$step3 = "Step 3: 限制管理端口 ($SshPort) 仅允许管理网段访问"
$log += $step3
Write-Host $step3

foreach ($network in $AdminNetworks) {
$ruleName = "Hardened - SSH from $network"
if (-not $WhatIf) {
New-FirewallAllowRule -Name $ruleName -Port $SshPort `
-Protocol TCP -RemoteAddress $network | Out-Null
}
$log += " -> 已允许: $network -> $SshPort/TCP"
}

# 第四步:禁用不必要的规则
$step4 = "Step 4: 禁用非必要预置规则"
$log += $step4
Write-Host $step4

$builtinDisabled = @()
$noisyRules = @(
"File and Printer Sharing (Echo Request - ICMPv4-In)"
"Network Discovery (NB-Datagram-In)"
"Network Discovery (NB-Name-In)"
)

foreach ($ruleName in $noisyRules) {
$rule = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue
if ($rule -and $rule.Enabled -eq "True") {
if (-not $WhatIf) {
$rule | Disable-NetFirewallRule | Out-Null
}
$builtinDisabled += $ruleName
}
}

$log += " -> 已禁用 $($builtinDisabled.Count) 条预置规则"

# 输出加固报告
$summary = @(
""
"========== 加固报告 =========="
"默认入站策略: Block"
"业务端口: $($AllowedInboundPorts -join ', ')"
"管理端口: $SshPort/TCP (限 $($AdminNetworks -join ', '))"
"禁用预置规则: $($builtinDisabled.Count) 条"
"WhatIf 模式: $WhatIf"
"================================"
)
$summary | ForEach-Object { Write-Host $_ }

return $log
}

执行结果示例(预览模式):

1
2
3
4
5
6
7
8
9
10
11
12
13
PS> Initialize-ServerFirewallHardening -WhatIf
Step 1: 设置默认入站策略为阻止
Step 2: 开放业务端口 (80, 443)
Step 3: 限制管理端口 (22) 仅允许管理网段访问
Step 4: 禁用非必要预置规则

========== 加固报告 ==========
默认入站策略: Block
业务端口: 80, 443
管理端口: 22/TCP (限 10.0.0.0/8, 172.16.0.0/12)
禁用预置规则: 3 条
WhatIf 模式: True
================================

小结

PowerShell 的 NetSecurity 模块让 Windows 防火墙管理变得完全可脚本化。核心命令只有四个——Get-NetFirewallRuleNew-NetFirewallRuleSet-NetFirewallRuleRemove-NetFirewallRule,但配合过滤器和管道可以覆盖几乎所有管理场景。实际运维中建议:始终使用 -WhatIf 预览变更、变更前导出备份、管理端口严格限制来源地址。将这些函数纳入 DSC 或 Ansible Playbook 中,就能实现防火墙策略的版本化管理和自动部署。