Skip to content

Instantly share code, notes, and snippets.

@jeffpatton1971
Created June 25, 2015 16:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeffpatton1971/d21e4248bb372983052c to your computer and use it in GitHub Desktop.
Save jeffpatton1971/d21e4248bb372983052c to your computer and use it in GitHub Desktop.
This function creates a FWRule ComObject that can be added to the firewall.
Function New-FirewallRule
{
<#
.SYNOPSIS
Creates a new HFnetCfg.FWRule ComObject
.DESCRIPTION
This function creates a FWRule ComObject that can be added to the firewall.
Each time you change a property of a rule, Windows Firewall commits the rule and verifies it for correctness.
As a result, when you edit a rule, you must perform the steps in a specific order. For example, if you add an ICMP
rule, you must first set the protocol to ICMP, then add the rule. If these steps are taken in the opposite order, an
error occurs and the change is lost. If you are editing a TCP port rule and converting it into an ICMP rule, first
delete the port, change protocol from TCP to ICMP, and then add the rule.
In order to retrieve and modify existing rules, instances of this interface must be retrieved through INetFwRules.
All configuration changes take place immediately.
When accessing the properties of a rule, keep in mind that there may be a small time lag before a newly-added
rule is applied.
Properties are used to create firewall rules. Many of the properties can be used in order to create very specific
firewall rules.
.PARAMETER Name
Specifies the friendly name of this rule. The string must not contain the "|" character.
.PARAMETER Action
Specifies the action for a rule or default setting.
.PARAMETER ApplicationName
Specifies the friendly name of the application to which this rule applies.
.PARAMETER Description
Specifies the description of this rule. The string must not contain the "|" character.
.PARAMETER Direction
Specifies the direction of traffic for which the rule applies. If this property is not specified, the default value is in.
.PARAMETER EdgeTraversal
Indicates whether edge traversal is enabled or disabled for this rule.
The EdgeTraversal property indicates that specific inbound traffic is allowed to tunnel through NATs and other edge devices
using the Teredo tunneling technology. In order for this setting to work correctly, the application or service with the
inbound firewall rule needs to support IPv6. The primary application of this setting allows listeners on the host to be
globally addressable through a Teredo IPv6 address.
New rules have the EdgeTraversal property disabled by default.
.PARAMETER Enabled
Enables or disables a rule. A new rule is disabled by default.
.PARAMETER Grouping
Specifies the group to which an individual rule belongs.
Using the Grouping property is highly recommended, as it groups multiple rules into a single line in the Windows Firewall
control panel. This allows the user to enable or disable multiple rules with a single click. The Grouping property can
also be specified using indirect strings. In this case, a group description can also be specified that will appear in the
rule group properties in the Windows Firewall control panel. For example, if the group string is specified by an indirect
string at index 1005 ("@yourresources.dll,-1005"), the group description can be specified at a resource string higher
by 10000 "@youresources.dll,-11005."
When indirect strings in the form of "h" are passed as parameters to the Windows Firewall with Advanced Security APIs,
they should either be placed under the System32 Windows directory or specified by a full path. Further, the file should
have a secure access that permits the Local Service account read access to allow the Windows Firewall Service to read the
strings. To avoid non-privileged security principals from modifying the strings, the DLLs should only allow write access
to the Administrator account.
.PARAMETER IcmpTypesAndCodes
Specifies the list of ICMP types and codes for this rule. The icmpTypesAndCodes parameter is a list of ICMP types and codes
separated by semicolon. "*" indicates all ICMP types and codes.
.PARAMETER Interfaces
Specifies the list of interfaces for which the rule applies. The interfaces in the list are represented by their friendly name.
.PARAMETER InterfaceTypes
Specifies the list of interface types for which the rule applies. Acceptable values for this property are "RemoteAccess",
"Wireless", "Lan", and "All". If more than one interface type is specified, the strings must be separated by a comma.
.PARAMETER LocalAddresses
Specifies the list of local addresses for this rule.
The localAddrs parameter consists of one or more comma-delimited tokens specifying the local addresses from which the application
can listen for traffic. "*" is the default value. Valid tokens include:
- "*" indicates any local address. If present, this must be the only token included.
- "Defaultgateway"
- "DHCP"
- "WINS"
- "LocalSubnet" indicates any local address on the local subnet. This token is not case-sensitive.
- A subnet can be specified using either the subnet mask or network prefix notation. If neither a
subnet mask not a network prefix is specified, the subnet mask defaults to 255.255.255.255.
- A valid IPv6 address.
- An IPv4 address range in the format of "start address - end address" with no spaces included.
- An IPv6 address range in the format of "start address - end address" with no spaces included.
.PARAMETER LocalPorts
Specifies the list of local ports for this rule. The Protocol property must be set before the LocalPorts property or an error will be returned.
.PARAMETER Protocol
Specifies the IP protocol of this rule. The Protocol property must be set before the LocalPorts or RemotePorts properties or an error will be returned.
.PARAMETER Profiles
Specifies the profiles to which the rule belongs.
.PARAMETER RemoteAddresses
Specifies the list of remote addresses for this rule.
The remoteAddrs parameter consists of one or more comma-delimited tokens specifying the remote addresses from which the application
can listen for traffic. The default value is "*". Valid tokens include:
- "*" indicates any remote address. If present, this must be the only token included.
- "Defaultgateway"
- "DHCP"
- "DNS"
- "WINS"
- "LocalSubnet" indicates any local address on the local subnet. This token is not case-sensitive.
- A subnet can be specified using either the subnet mask or network prefix notation. If neither a
subnet mask not a network prefix is specified, the subnet mask defaults to 255.255.255.255.
- A valid IPv6 address.
- An IPv4 address range in the format of "start address - end address" with no spaces included.
- An IPv6 address range in the format of "start address - end address" with no spaces included.
.PARAMETER RemotePorts
Specifies the list of remote ports for this rule. The Protocol property must be set before the RemotePorts property or an error will be returned.
.PARAMETER ServiceName
Specifies the service name property of the application. A serviceName value of "*" indicates that a service, not an application, must
be sending or receiving traffic.
#>
[CmdletBinding()]
[OutputType([__ComObject])]
Param
(
[Parameter(Position=0,Mandatory=$true)]
[ValidateScript({(!($_.Contains('|')) -and !($_.ToLower().Contains('any')))})]
[string]$Name,
[Parameter(Position=1,Mandatory=$false)]
[ValidateScript({(!($_.ToLower().Contains('any')))})]
[string]$Description,
[Parameter(Position=2,Mandatory=$false)]
[string]$ApplicationName,
[Parameter(Position=3,Mandatory=$false)]
[string]$ServiceName,
[Parameter(Position=4,Mandatory=$false)]
[ValidateSet('ICMPv4','IGMP','TCP','UDP','IPv6','IPv6Route','IPv6Frag','GRE','ICMPv6','IPv6NoNxt','IPv6Opts','VRRP','PGM','L2TP')]
[String]$Protocol,
[Parameter(Position=5,Mandatory=$false)]
[string[]]$LocalPorts,
[Parameter(Position=6,Mandatory=$false)]
[string[]]$RemotePorts,
[Parameter(Position=7,Mandatory=$false)]
[string[]]$LocalAddresses = @('*'),
[Parameter(Position=8,Mandatory=$false)]
[string[]]$RemoteAddresses = @('*'),
[Parameter(Position=7,Mandatory=$false)]
[string]$IcmpTypesAndCodes,
[Parameter(Position=9,Mandatory=$false)]
[ValidateSet('In','Out')]
[string]$Direction = 'In',
[Parameter(Position=10,Mandatory=$false)]
[string]$Interfaces,
[Parameter(Position=11,Mandatory=$false)]
[ValidateSet('RemoteAccess','Wireless','Lan','All')]
[string[]]$InterfaceTypes,
[Parameter(Position=12,Mandatory=$false)]
[bool]$Enabled = $false,
[Parameter(Position=13,Mandatory=$false)]
[string]$Grouping,
[Parameter(Position=14,Mandatory=$false)]
[ValidateSet('Domain','Private','Public','Any')]
[string[]]$Profiles,
[Parameter(Position=15,Mandatory=$false)]
[bool]$EdgeTraversal = $false,
[Parameter(Position=16,Mandatory=$false)]
[ValidateSet('Allow','Block')]
[string]$Action
)
Begin
{
$ProtocolLookup = @{'ICMPv4'=1;'IGMP'=2;'TCP'=6;'UDP'=17;'IPv6'=41;'IPv6Route'=43;'IPv6Frag'=44;'GRE'=47;'ICMPv6'=48;'IPv6NoNxt'=59;'IPv6Opts'=60;'VRRP'=112;'PGM'=113;'L2TP'=115};
$ProfileLookup = @{'Domain'=1; 'Private'=2;'Public'=4};
}
Process
{
try
{
$Error.Clear();
$ErrorActionPreference = 'Stop';
$Rule = New-Object -ComObject "HNetCfg.FWRule";
switch ($Action)
{
'Allow'
{
$Rule.Action = 1;
}
'Block'
{
$Rule.Action = 0;
}
}
$Rule.ApplicationName = $ApplicationName;
$Rule.Description = $Description;
switch ($Direction)
{
'In'
{
$Rule.Direction = 1;
}
'Out'
{
$Rule.Direction = 0;
}
}
$Rule.EdgeTraversal = $EdgeTraversal;
$Rule.Enabled = $Enabled;
$Rule.Grouping = $Grouping;
if ($IcmpTypesAndCodes)
{
$Rule.IcmpTypesAndCodes = $IcmpTypesAndCodes;
}
if ($Interfaces)
{
$Rule.Interfaces = $Interfaces;
}
$Rule.InterfaceTypes = $InterfaceTypes;
$Rule.LocalAddresses = [System.String]::Join(',',$LocalAddresses);
$Rule.Protocol = $ProtocolLookup.Keys |Where-Object {$_ -eq $Protocol} |ForEach-Object {$ProtocolLookup.Item($_)};
if ($LocalPorts)
{
$Rule.LocalPorts = $LocalPorts;
}
$Rule.Name = $Name;
if ($Profiles)
{
[int]$Count = 0;
foreach ($P in $Profiles)
{
$Count += $ProfileLookup.Keys |Where-Object {$_ -eq $P} |ForEach-Object {$ProfileLookup.Item($_)};
}
$Rule.Profiles = $Count;
if ($Profiles.Contains('Any'))
{
$Rule.Profiles = 2147483647;
}
}
$Rule.RemoteAddresses = [System.String]::Join(',',$RemoteAddresses);
if ($RemotePorts)
{
$Rule.RemotePorts = $RemotePorts;
}
$Rule.serviceName = $ServiceName;
return $Rule;
}
catch
{
throw $_
}
}
End
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment