16236

Controlling Firewall Rules

I decide that for this module I wanted some functions that control specific rule that I could be working with often e.g. Enable/Disable WMI rules and then I want a generic function for everything else.

Lets start with some specifics. If we look at the WMI rules

get-rule | where{$_.Name -like "*wmi*"}

we get this output.

Action    : Allow
Name      : Windows Management Instrumentation (WMI-Out)
Profile   : {Private, Public}
Direction : Outbound
Protocol  : TCP

Action    : Allow
Name      : Windows Management Instrumentation (WMI-In)
Profile   : {Private, Public}
Direction : Inbound
Protocol  : TCP

Action    : Allow
Name      : Windows Management Instrumentation (WMI-Out)
Profile   : {Domain}
Direction : Outbound
Protocol  : TCP

Action    : Allow
Name      : Windows Management Instrumentation (WMI-In)
Profile   : {Domain}
Direction : Inbound
Protocol  : TCP

As they are enabled we’ll start by looking at disabling them.

function disable-wmi {             
[CmdletBinding()]             
param (            
             
 [parameter(ParameterSetName="Inbound")]            
 [switch]$in,            
             
 [parameter(ParameterSetName="Outbound")]            
 [switch]$out,            
             
 [switch]$domain,            
 [switch]$private,            
 [switch]$public            
)             
BEGIN{}#begin             
PROCESS{            
$fw = New-Object -ComObject HNetCfg.FwPolicy2            
            
switch ($psCmdlet.ParameterSetName) {            
 "Inbound"  {$direction = 1 }            
 "Outbound"  {$direction = 2 }            
 default {Write-Host "Error!!! Should not be here" }            
}            
            
            
$fw.Rules | where {$_.Name -like "Windows Management Instrumentation*" -and $_.Direction -eq $direction} |            
foreach {            
 #$_            
 if($domain -and ($_.profiles -eq 1)) {$_.Enabled = $false}             
 if($private -and ($_.profiles -eq 2)) {$_.Enabled = $false}              
 if($public -and ($_.profiles -eq 4)) {$_.Enabled = $false}              
            
 if($domain -and ($_.profiles -band 1)) {$_.Enabled = $false}             
 if($private -and ($_.profiles -band 2)) {$_.Enabled = $false}              
 if($public -and ($_.profiles -band 4)) {$_.Enabled = $false}              
            
            
}            
            
}#process             
END{}#end            
            
<# 
.SYNOPSIS
Disables WMI through firewall

.DESCRIPTION
Disables WMI through firewall
 

.EXAMPLE
disable-wmi -in -domain

.EXAMPLE
disable-wmi -in -domain -pp

.EXAMPLE
disable-wmi -out  -pp

#>            
            
}


I’ve used parameter sets to distinguish in and outbound rules. The network types are set as switches.



The rules are scanned and depending on the network type and profile the Enabled property is set to $false. I’ve tested the profile as an equals and as a –band to catch the singleton and mixed profile

Firewall rules (OK)

The really important thing about our firewall is the rules that are configured.

function get-rule {             
[CmdletBinding()]             
param ()             
BEGIN{}#begin             
PROCESS{            
$fw = New-Object -ComObject HNetCfg.FwPolicy2            
$fw.Rules |            
foreach {            
            
$profiles = @()            
$ruleprofile = $_.Profiles            
            
@(1,2,4, 1073741824) |             
foreach {            
  if ($_ -band $ruleprofile){$profiles += [ProfileType]($_)}            
}            
              
 $rule = New-Object -TypeName PSObject -Property @{            
     Name = $_.Name            
     Protocol = [Protocol]($_.Protocol)            
     Direction = [Direction]($_.Direction)            
     Profile = $profiles            
     Action = [Action]($_.Action)            
   }            
 $rule.PSTypeNames[0] = "FirewallRule"            
 $rule            
            
}            
            
}#process             
END{}#end            
            
<# 
.SYNOPSIS
Displays firewall rules

.DESCRIPTION
Displays firewall rules.
Properties are:
 Name
 Protocol
 Direction
 Profile
 Action 
 

.EXAMPLE
get-rule

get-rule | format-table -AutoSize -Wrap
#>            
            
}


Start with the HNetCfg.FwPolicy2   object. Put the Rules collection onto the pipeline. check each of the possible profiles and add them to the array.



An output object is created with the properties converted from their numeric values to descriptive values using a few more enumerations.



Suggested usage:



get-rule



get-rule | format-table -AutoSize -Wrap

Windows firewall

I normally leave the Windows firewall enabled in my test environment. It ensures I don’t forget it when testing. My recent session for the TechEd:Australia PowerShell conference involved me disabling various firewall rules on the subject machine to set up part of the demo. I had to use the GUI tools to do this. I'’ve moaned to myself that I needed some PowerShell tools for working with the firewall especially as the netsh syntax has changed in Windows 2008 R2 – the session has prompted me to do something about it.

James O’Neill has written a very nice Configurator module for setting up servers. I’ve borrowed some of his ideas but as I’m just working with the firewall I thought I’d be a bit more verbose in the way I do things.

First off I want to know which network types are enabled on my machine. I need to consider them when working with  firewall rules.

I’m creating these functions as a module so I can define my networks (firewall profiles) in the .psm1 file

## types            
Add-type @"
public enum ProfileType {
 Domain   = 1,
 Private  = 2,
 Public   = 4,
 All      = 1073741824
} 
"@            
            
## functions            
. $psScriptRoot/Get-Profile.ps1


I can use this enum in the function to display the firewall profiles



function get-profile {             
[CmdletBinding()]             
param ()             
BEGIN{}#begin             
PROCESS{            
$fw = New-Object -ComObject HNetCfg.FwPolicy2            
$fwtypes = $fw.CurrentProfileTypes            
            
@(1,2,4) |             
foreach {            
 $cpt = New-Object -TypeName PSObject -Property @{            
     Enabled = $false            
     Profile = [ProfileType]($_)             
   }            
 $cpt.PSTypeNames[0] = "FirewallProfile"            
             
 if ($_ -band $fwtypes){$cpt.Enabled = $true}            
 $cpt             
}            
            
}#process             
END{}#end            
            
<# 
.SYNOPSIS
Determines active firewall profiles

.DESCRIPTION
Determines active firewall profiles.
Possible values are:
 Domain
 Private 
 Public

.EXAMPLE
get-profile

#>            
            
}


The function gets the firewall COM object. For the three network types we create an object that gives the name and that its disabled. We change the object type and then if test if the value and the firewall CurrentProfileTypes property can band. If they do we set the profile to enabled ($true). The object is displayed.



Output looks like this



PS> get-profile | ft -a



Profile Enabled
------- -------
Domain   False
Private    True
Public    True