6.2. Obtaining a List of Rules
Before you can learn much about the rule technique
for working with the Windows Firewall, you must know how to enumerate
the rules. The rules provide considerably more information than older
Windows Firewall techniques. For example, you can discover precisely
which profile a rule appears in and determine both local and remote
addresses. The code shown in Listing 10
doesn't include all the information you can obtain from a rule, but it
gives you a good start on the most commonly used bits of information.
Example 10. Obtaining a list of Windows Firewall rules
private void btnGetRules_Click(object sender, EventArgs e) { // Clear the old entries. lstRuleList.Items.Clear();
// Define a GPO policy type. Type PolicyType = Type.GetTypeFromProgID("HNetCfg.FwPolicy2");
// Create the policy object. dynamic Policy = Activator.CreateInstance(PolicyType);
// Determine whether the firewall is enabled in specific profiles. lstRuleList.Items.Add("Domain Firewall is Enabled: " + Policy.FirewallEnabled(NET_FW_PROFILE2_DOMAIN)); lstRuleList.Items.Add("Public Firewall is Enabled: " + Policy.FirewallEnabled(NET_FW_PROFILE2_PUBLIC)); lstRuleList.Items.Add("Private Firewall is Enabled: " + Policy.FirewallEnabled(NET_FW_PROFILE2_PRIVATE));
// Process each rule in turn. lstRuleList.Items.Add(""); lstRuleList.Items.Add("Rules:"); lstRuleList.Items.Add(""); foreach (dynamic Rule in Policy.Rules) { // Use only the enabled rules. if (Rule.Enabled) { // Output the rule name. lstRuleList.Items.Add("Rule Name: " + Rule.Name);
// Output the associated application. lstRuleList.Items.Add("Application: " + Rule.ApplicationName);
// Display the rule's description. lstRuleList.Items.Add("Description: " + Rule.Description);
// Output the rule's group. lstRuleList.Items.Add("Grouping: " + Rule.Grouping);
// Determine the associated profiles.
if (Rule.Profiles == NET_FW_PROFILE2_ALL) lstRuleList.Items.Add("All Profiles"); else { if ((Rule.Profiles & NET_FW_PROFILE2_DOMAIN) == NET_FW_PROFILE2_DOMAIN)
lstRuleList.Items.Add("Domain Profile");
if ((Rule.Profiles & NET_FW_PROFILE2_PRIVATE) == NET_FW_PROFILE2_PRIVATE)
lstRuleList.Items.Add("Private Profile");
if ((Rule.Profiles & NET_FW_PROFILE2_PUBLIC) == NET_FW_PROFILE2_PUBLIC)
lstRuleList.Items.Add("Public Profile"); }
// Determine whether the rule is inbound or outbound. switch ((Int32)Rule.Direction) { case NET_FW_RULE_DIR_IN: lstRuleList.Items.Add("Inbound Rule"); break; case NET_FW_RULE_DIR_OUT: lstRuleList.Items.Add("Outbound Rule"); break; }
// Determine whether the rule allows or blocks an action. switch ((Int32)Rule.Action) { case NET_FW_ACTION_ALLOW: lstRuleList.Items.Add("Allow Action"); break; case NET_FW_ACTION_BLOCK: lstRuleList.Items.Add("Block Action"); break; }
// Determine the rule's protocol. switch ((Int32)Rule.Protocol) { case NET_FW_IP_PROTOCOL_ICMPv4: lstRuleList.Items.Add("ICMP v4"); break; case NET_FW_IP_PROTOCOL_ICMPv6: lstRuleList.Items.Add("ICMP v6"); break; case NET_FW_IP_PROTOCOL_TCP:
lstRuleList.Items.Add("TCP"); break; case NET_FW_IP_PROTOCOL_UDP: lstRuleList.Items.Add("UDP"); break; default: lstRuleList.Items.Add("Other Protocol"); break; }
// Display the local addresses and ports. lstRuleList.Items.Add("Local Addresses: " + Rule.LocalAddresses); lstRuleList.Items.Add("Local Ports: " + Rule.LocalPorts);
// Display the remote addresses and ports. lstRuleList.Items.Add("Remote Addresses: " + Rule.RemoteAddresses); lstRuleList.Items.Add("Remote Ports: " + Rule.RemotePorts);
// Add a space between entries. lstRuleList.Items.Add(""); } } }
|
The example begins by clearing the old list entries. It then creates a new Type, PolicyType, using the HNetCfg.FwPolicy2 program identifier. This technique doesn't rely on the Windows Firewall Manager; it uses policies instead, so you start with a Policy object. The next step is to create the Policy object using the Activator.CreateInstance() with the PolicyType as an argument.
One Policy object can work with multiple profiles. The code demonstrates this fact by obtaining the FirewallEnabled
property value for all three profiles. To check this out, try turning
off one of the firewall configurations in the Windows Firewall applet —
the status will change for the appropriate profile in the application.
You won't always use the technique shown for the FirewallEnabled property to work with a specific profile, but you'll use it in some cases, so keep it in mind.
The next step is to show the content of each of the enabled rules for the system. The example uses a foreach loop with a dynamic variable, Rule,
to perform this task. Many of the standard Windows Firewall rules
aren't enabled, so one of the first checks you'll normally perform is
to verify the enabled status of the rule. The example uses an if statement with Rule.Enabled to accomplish this task.
Most of the Rule entries are
straightforward. A rule has a name and description. Application
exceptions will also include an application name with a full path to
the application. A grouping is a method of ordering associated rules
together. You need to create an application resource to accomplish this
task, but the technique for doing so is outside the scope of this
discussion.
Determining which profile a rule is part of is a
little cumbersome. First, you need to determine whether the rule is
part of all the profiles by checking the Profiles property against NET_FW_PROFILE2_ALL.
If the rule doesn't exist in all the profiles, it must exist in at
least one profile and could exist in two. The series of three if statements that comes next checks for each of these possibilities.
A rule is inbound (meaning it checks the incoming
data stream) or outbound (meaning it checks the outgoing data stream),
but never both. The next check verifies that the rule is either inbound
or outbound. A rule can also allow or block an action, so that's the
next check. Rules can use a host of different protocols, but they use
only one protocol at a time. For example, a rule can't service both TCP
and UDP. To provide both TCP and UDP support, you must create two
rules. The example checks against four different common protocols. If
none of these protocols is valid, the check simply reports that the
rule is using some other protocol.
The last check determines the local and
remote addresses and ports for the rule. Working with rules lets you
assign both local and remote addresses and ports.