2

I got the current script (from this answer) which I want to improve.

The script should retrieve the desired ports if they are enabled and allowed within the inbound direction. Filters for Action/Enabled/Direction work perfectly but I still need that the filters for the Local ports will retrieve only unique results within the defined ports but still show other ports as well.

Additional question:

  1. how do I add the IP of the machine to the query?
  2. I would like to use AsBuiltReport to publish the results. How does it do?
  3. I would like to trigger it remotely I do it through invoke command but if there is a best practice for this I would like to be aware of that.
  4. How can I have only the relevant ports I mentioned and not anything else?

`

Get-NetFirewallRule -Action Allow -Enabled True -Direction Inbound | 
  Where-Object { 
    $portFilter = $PSItem | Get-NetFirewallPortFilter | Select-Object -Unique
    $portFilter.LocalPort -match '^(80|135|139|445|5985|5986)$' -or 
      ($portFilter.LocalPort -ge 49152 -and $portFilter.LocalPort -le 65535)} |
      Format-Table Name,Profile,
Enabled,
Direction,
Action,
@{Name='Protocol';Expression={($PSItem | Get-NetFirewallPortFilter).Protocol}},
@{ Name='LocalPort'; Expression={$portFilter.LocalPort | Select-Object -Unique}},
@{Name='RemotePort';Expression={($PSItem | Get-NetFirewallPortFilter).RemotePort}}


`

Thanks

I put the Select-Object -Unique before the filters to get only unique results.

I put -match before the relevant ports and conditions for the range port.

I expect the query to result unique values with the coming ports Ports 80 or 135 or 139 or 445 or 5985 or 5986 or range between 49152 and 65535

  • Should be faster with get-netfirewallportfilter first, for example: `Get-NetFirewallPortFilter | ? { $_.localport -match '80|135|139|445|5985|5986' } | Get-NetFirewallRule` – js2010 Nov 11 '22 at 16:24
  • As for question 2: It's unclear what AsBuiltReport is, and it sounds like you should (eventually) ask a separate question with more context. As for question 3: [`Invoke-Command`](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/invoke-command), i.e. use of [PowerShell remoting](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_remote_requirements), is indeed the recommended way to execute commands remotely. – mklement0 Nov 11 '22 at 16:55
  • For question 1: which IP address? Try out `(Get-NetIPAddress | Where IPAddress -like '10.0.*').IPv4Address` and put in the right subnet address you expect – Cpt.Whale Nov 11 '22 at 18:32
  • Using AsBuiltReport is great, but be aware that powershell remoting with `Invoke-Command` can make it difficult to write that report out to another location: `LocalPC --> RemotePC -X-> FileShare` – Cpt.Whale Nov 11 '22 at 18:35
  • Windows firewall rules use Application, source Address, or Interface filters too, which can allow traffic *without* needing to specify a port – Cpt.Whale Nov 11 '22 at 18:59
  • And since you mentioned GPO... firewall rules applied by GPO go into a different policy store, so use `Get-NetFirewallRule -PolicyStore ActiveStore` to include all the active ones – Cpt.Whale Nov 11 '22 at 19:01
  • Hi everyone thank's for the answers I updated the questions and add one more question (4). @js2010 regarding your note not sure how to write it correctly. mklement0 I will check that out thanks. Cpt.Whale thanks for the remarks. Right now I only need to look for the ports I mentioned but I'll think about how to handle this. Please give me an example of how it can be manipulated. Do active means enable + allowed or only enable? – user1568050 Nov 11 '22 at 21:42
  • Hi, @js2010 can you make your note clear, please? Also, why do I get back additional ports when I filter? – user1568050 Nov 12 '22 at 22:56
  • Hi @Cpt.Whale do you mean that it will be hard to write the report back to the machine where I'm triggering the remote command? – user1568050 Nov 12 '22 at 23:27

1 Answers1

1

Here's how I would do it. Takes about 8 seconds. With invoke-command, pscomputername has the hostname, and there's also a runspaceid. -pv is pipelinevariable. I have to put get-netfirewallrule inside % or foreach-object so it runs for every instance of the port info.

Annoying how localport can be an object array or a string with dashes or a word like 'Any'. Filtering them numerically is problemmatic.

LocalPort                    type
---------                    ----
546                          System.String
{554, 8554-8558}             System.Object[]
5000-5020                    System.String
{554, 8554, 8555, 8556...}   System.Object[]
{80, 443}                    System.Object[]
Any                          System.String
IPHTTPSIn                    System.String
PlayToDiscovery              System.String
RPC                          System.String
RPCEPMap                     System.String
Teredo                       System.String

1024-65535
5000-5020
8554-8558
7200-17210
invoke-command localhost { Get-NetFirewallPortFilter | 
  ? {
  80 -in $_.localport -or
  135 -in $_.localport -or
  139 -in $_.localport -or
  445 -in $_.localport -or
  5985 -in $_.localport -or
  5986 -in $_.localport -or
  $(if($_.localport -as 'int') { ([int]$_.LocalPort -ge 49152 -and
    [int]$_.LocalPort -le 65535) } )
  } -pv port | 
  % { $_ | Get-NetFirewallRule } |
  ? { $_.action -eq 'allow' -and $_.enabled -eq $true -and
  $_.direction -eq 'inbound' } | 
  select Name,Profile,Enabled,Direction,Action,
  @{n='Protocol';e={$port.Protocol}},
  @{n='Localport';e={$port.Localport}},
  @{n='Remoteport';e={$port.Remoteport}} } | ft -a


Name                          Profile         Enabled Direction Action Protocol Localport Remoteport PSComputerName RunspaceId
----                          -------         ------- --------- ------ -------- --------- ---------- -------------- ----------
WINRM-HTTP-In-TCP-NoScope     Domain, Private True    Inbound   Allow  TCP      5985      Any        localhost      8366c72c-e868-4e50-adb5-85c4deea3583
WINRM-HTTP-In-TCP             Public          True    Inbound   Allow  TCP      5985      Any        localhost      8366c72c-e868-4e50-adb5-85c4deea3583
IIS-WebServerRole-HTTP-In-TCP Any             True    Inbound   Allow  TCP      80        Any        localhost      8366c72c-e868-4e50-adb5-85c4deea3583
js2010
  • 23,033
  • 6
  • 64
  • 66
  • Hi @js2010 thank you!! Three notes: 1. I only need to know if the ports from the list appear once and no matter where 2. It still show more then the filtered ports in the result. For example: 7680, 546,5353,5355,5355,5357-8,554, 8554-8558, 5000-5020,7200-17210,8889,5000, 7000, 7100, 50000 etc... 3. I need to query this on remote host so hard typing localhost would be concern. What can I put instead? – user1568050 Nov 13 '22 at 16:07
  • localhost can be any comma seperated list of hosts – js2010 Nov 13 '22 at 16:21
  • Not sure I understand how to make the list outside the script since I'm lunching it remotely.... Also, can you please relate to questions (1) and (2) in advance? – user1568050 Nov 13 '22 at 16:33
  • Got your update @js2010. How would you suggest handling it as simply as possible or is there a way to handle it? Is it sure that I will get ---at least--- the filtered ports that I want within the results using the filter? – user1568050 Nov 13 '22 at 17:14
  • I took a shot at it. It doesn't take 'any' or dash ranges into account. There's only 3 results for me. Checking 49152-65535 won't work with an array. – js2010 Nov 13 '22 at 17:24
  • Thank you. Does it mean that we can not check for port status in the range of 49152-65535? – user1568050 Nov 14 '22 at 11:44
  • You would have to do extra parsing. On my machine, only the string "1024-65535" would match. – js2010 Nov 14 '22 at 13:23