基于AsBuiltReport框架优化PowerShell GPO端口查询脚本
优化后的防火墙入站允许端口查询脚本
针对需求优化后的脚本,解决了LocalPort去重、精准过滤指定端口的问题,同时减少重复调用Get-NetFirewallPortFilter的性能损耗:
# 定义需要保留的固定端口和动态端口范围 $targetFixedPorts = '80','135','139','445','5985','5986' $targetPortRangeStart = 49152 $targetPortRangeEnd = 65535 Get-NetFirewallRule -Action Allow -Enabled True -Direction Inbound | ForEach-Object { # 一次性获取端口过滤器,避免重复调用 $portFilter = $_ | Get-NetFirewallPortFilter # 提取并筛选符合条件的LocalPort,同时去重 $validLocalPorts = $portFilter.LocalPort | Where-Object { $_ -in $targetFixedPorts -or ($_ -ge $targetPortRangeStart -and $_ -le $targetPortRangeEnd) } | Select-Object -Unique # 仅保留有有效端口的规则 if ($validLocalPorts) { [PSCustomObject]@{ Name = $_.Name Profile = $_.Profile Enabled = $_.Enabled Direction = $_.Direction Action = $_.Action Protocol = $portFilter.Protocol LocalPort = $validLocalPorts -join ',' RemotePort = $portFilter.RemotePort } } } | Format-Table -AutoSize
额外问题解答
1. 如何在查询结果中添加机器IP?
有两种常用实现方式:
- 获取当前网络连接的IPv4地址:在生成自定义对象时添加计算属性,优先取活跃网络接口的IP:
MachineIP = (Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias (Get-NetConnectionProfile).InterfaceAlias).IPAddress - 获取所有绑定的IPv4地址:如果需要列出机器所有IPv4地址,可改用:
远程执行时,上述代码会自动获取目标机器的IP,无需额外处理。MachineIP = ([System.Net.Dns]::GetHostAddresses($env:COMPUTERNAME) | Where-Object {$_.AddressFamily -eq 'InterNetwork'}).IPAddressToString -join ','
2. 如何使用AsBuiltReport发布查询结果?
AsBuiltReport用于生成标准化架构报告,整合防火墙端口数据的步骤如下:
- 先安装依赖模块:
Install-Module -Name AsBuiltReport -Force Install-Module -Name AsBuiltReport.Core -Force - 保存查询结果为对象数组:
$firewallData = Get-NetFirewallRule -Action Allow -Enabled True -Direction Inbound | ForEach-Object { # 复用优化后的脚本逻辑生成数据对象 $portFilter = $_ | Get-NetFirewallPortFilter $validLocalPorts = $portFilter.LocalPort | Where-Object { $_ -in $targetFixedPorts -or ($_ -ge $targetPortRangeStart -and $_ -le $targetPortRangeEnd) } | Select-Object -Unique if ($validLocalPorts) { [PSCustomObject]@{ Name = $_.Name Profile = $_.Profile Enabled = $_.Enabled Direction = $_.Direction Action = $_.Action Protocol = $portFilter.Protocol LocalPort = $validLocalPorts -join ',' RemotePort = $portFilter.RemotePort MachineIP = (Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias (Get-NetConnectionProfile).InterfaceAlias).IPAddress } } } - 配置并生成报告:
生成的报告会自动将防火墙端口数据整合到指定章节,支持多格式输出。$reportConfig = @{ ReportName = 'Windows Firewall Audit Report' OutputPath = 'C:\AuditReports' Format = 'HTML','Word' CustomContent = @{ 'Allowed Inbound Firewall Ports' = $firewallData } } New-AsBuiltReport -InputObject $env:COMPUTERNAME -ReportConfig $reportConfig -EnableHealthCheck
3. Invoke-Command远程触发脚本的最佳实践
- 会话复用:用
New-PSSession建立持久会话,避免每次调用重新创建连接:$session = New-PSSession -ComputerName 'RemotePC01' Invoke-Command -Session $session -ScriptBlock { # 脚本内容 } Remove-PSSession $session - 最小权限原则:使用具备必要权限的域账户执行操作,避免用管理员账户;通过组策略限制WinRM允许访问的用户。
- 加密通信:配置WinRM使用HTTPS,防止明文传输:
winrm quickconfig -transport:https - 规范参数传递:用
-ArgumentList或$using:作用域传递本地变量,避免硬编码:$targetPorts = '80','445' Invoke-Command -ComputerName 'RemotePC01' -ScriptBlock { param($ports) Write-Host $ports } -ArgumentList $targetPorts # 或使用$using: Invoke-Command -ComputerName 'RemotePC01' -ScriptBlock { Write-Host $using:targetPorts } - 错误与日志处理:结合
try/catch捕获异常,记录操作日志:try { Invoke-Command -ComputerName 'RemotePC01' -ScriptBlock { # 脚本 } -ErrorAction Stop } catch { Write-Error "远程执行失败:$_" Add-Content -Path 'C:\Logs\RemoteAudit.log' -Value "$(Get-Date) - 错误:$_" } - 批量执行优化:针对多台机器,用
-ComputerName传入数组,结合-ThrottleLimit控制并发数,避免资源耗尽。
4. 如何仅保留指定端口(固定端口+动态端口范围)
优化后的脚本已实现该逻辑,核心步骤:
- 预先定义目标固定端口数组和动态端口范围的起止值;
- 对每个防火墙规则的LocalPort进行筛选:判断端口是否在固定列表内,或处于指定动态端口范围;
- 用
Select-Object -Unique对筛选后的端口去重; - 仅保留存在有效端口的规则,确保结果只包含符合要求的端口数据。
内容的提问来源于stack exchange,提问作者user1568050
相关产品推荐
相关产品推荐

