PowerShell查询GPO防火墙端口问题及AsBuiltReport适配咨询
多台远程服务器防火墙GPO端口查询相关问题解答
背景
需要在多台远程服务器上查询防火墙GPO端口,先编写了本地查询的PowerShell脚本,但整合查询结果时遇到问题。当前脚本如下:
Get-NetFirewallRule -Action Allow -Enabled True -Direction Inbound | Select-Object -Unique | Where-Object {$_.LocalPort -eq 7680}| Format-Table -Property Profile, Enabled, Direction, @{Name='Protocol';Expression={($PSItem | Get-NetFirewallPortFilter).Protocol}}, @{Name='LocalPort';Expression={($PSItem | Get-NetFirewallPortFilter).LocalPort}}, @{Name='RemotePort';Expression={($PSItem | Get-NetFirewallPortFilter).RemotePort}}, @{Name='RemoteAddress';Expression={($PSItem | Get-NetFirewallAddressFilter).RemoteAddress}}, Profile
问题解答
1. 如何使用Where-Object过滤指定本地端口及端口范围?
你之前修改失败的核心原因是:Get-NetFirewallRule返回的对象本身没有LocalPort属性,这个属性需要从关联的Get-NetFirewallPortFilter结果中获取。正确的做法是先获取端口过滤规则,再基于此做条件判断,同时整合你需要的过滤逻辑:
修改后的脚本示例:
Get-NetFirewallRule -Action Allow -Enabled True -Direction Inbound | ForEach-Object { $portFilter = $_ | Get-NetFirewallPortFilter # 解析端口值,兼容单个端口、端口范围格式 $localPorts = $portFilter.LocalPort -split ',' | ForEach-Object { if ($_ -match '(\d+)-(\d+)') { [int]$matches[1]..[int]$matches[2] } else { [int]$_ } } # 判断是否符合过滤条件 if ( ($localPorts | Where-Object { $_ -in 80,135,139,445,5985,5986 }) -or ($localPorts | Where-Object { $_ -ge 49152 -and $_ -le 65535 }) ) { $_ | Select-Object -Property Profile, Enabled, Direction, @{Name='Protocol';Expression={$portFilter.Protocol}}, @{Name='LocalPort';Expression={$portFilter.LocalPort}}, @{Name='RemotePort';Expression={$portFilter.RemotePort}}, @{Name='RemoteAddress';Expression={($_ | Get-NetFirewallAddressFilter).RemoteAddress}} } } | Format-Table -AutoSize
说明:
- 遍历每条防火墙规则,先获取对应的端口过滤对象
- 解析
LocalPort字段,适配单个端口(如80)和端口范围(如49152-65535)的格式 - 按要求的条件过滤:匹配指定端口,或端口落在49152-65535区间内
- 输出结构化结果,移除重复的
Profile字段
2. 是否更适合使用netsh替代当前方法?
不推荐用netsh替代,原因如下:
Get-NetFirewallRule是PowerShell原生的CIM cmdlet,返回结构化对象,方便后续过滤、排序、导出(CSV/JSON)以及整合进其他脚本逻辑netsh advfirewall firewall show rule的输出是纯文本,需要手动解析字符串,处理繁琐且易出错- 仅在旧版本Windows(如Windows Server 2008 R2及更早)不支持
NetSecurity模块时,才考虑把netsh作为备选
3. 如何自定义查询结果并在AsBuiltReport框架中展示?
核心是将查询结果整理为结构化对象,再适配框架的输出逻辑:
- 整理结构化数据:避免用
Format-Table(会将对象转为格式化输出对象,无法后续处理),用Select-Object输出纯对象集合,示例函数如下:
function Get-FirewallGpoPorts { Get-NetFirewallRule -Action Allow -Enabled True -Direction Inbound | ForEach-Object { $portFilter = $_ | Get-NetFirewallPortFilter $addrFilter = $_ | Get-NetFirewallAddressFilter [PSCustomObject]@{ Profile = $_.Profile Enabled = $_.Enabled Direction = $_.Direction Protocol = $portFilter.Protocol LocalPort = $portFilter.LocalPort RemotePort = $portFilter.RemotePort RemoteAddress = $addrFilter.RemoteAddress } } | Where-Object { # 加入端口过滤逻辑 $localPorts = $_.LocalPort -split ',' | ForEach-Object { if ($_ -match '(\d+)-(\d+)') { [int]$matches[1]..[int]$matches[2] } else { [int]$_ } } ($localPorts | Where-Object { $_ -in 80,135,139,445,5985,5986 }) -or ($localPorts | Where-Object { $_ -ge 49152 -and $_ -le 65535 }) } }
- 整合到AsBuiltReport框架:
- 在报告对应章节(如“防火墙配置”)调用上述函数获取数据
- 使用框架的
Add-AsBuiltReportSection创建章节,再用New-AsBuiltReportTable将数据转为报告表格 - 可自定义表格列标题、样式,示例代码:
$firewallData = Get-FirewallGpoPorts if ($firewallData) { Add-AsBuiltReportSection -Type 'Table' -Name '防火墙GPO允许入站端口' -Data $firewallData -Columns @( @{Name='配置文件'; Expression={$_.Profile}}, @{Name='启用状态'; Expression={$_.Enabled}}, @{Name='方向'; Expression={$_.Direction}}, @{Name='协议'; Expression={$_.Protocol}}, @{Name='本地端口'; Expression={$_.LocalPort}}, @{Name='远程端口'; Expression={$_.RemotePort}}, @{Name='远程地址'; Expression={$_.RemoteAddress}} ) }
这样就能将自定义的防火墙端口查询结果以规范表格形式展示在AsBuiltReport生成的文档中。
内容的提问来源于stack exchange,提问作者user1568050
相关产品推荐
相关产品推荐

