Learn about Windows PowerShell
Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell to create new Windows Firewall rules on local and remote systems.
Microsoft Scripting Guy, Ed Wilson, is here. Today, we are off to Europe. The Scripting Wife and I are actually on separate flights—it’s the way the airline miles worked out for the flight. Luckily, the Scripting Wife is an excellent traveler. When I was working in Vienna a few years ago, she flew into Frankfurt, hopped a train to Vienna, and navigated the local S-Bahn trains from the Ost-Bahnhoff to the hotel without incident.
Anyway, from Frankfurt, once we are all there, we hop a train to Dortmond, Germany, where we will meet with Klaus Schulte. Klaus, as you may know, was the winner of the Scripting Games, and he has written several guest Hey, Scripting Guy! Blog posts. Neither the Scripting Wife nor myself has been to Dortmond, and we are looking forward to hanging out with Klaus, taking pictures, and of course, talking about Windows PowerShell.
I know why we do it, but dude, I still like to use Ping to see if a computer is up or down. I know I can use Windows PowerShell and do something like Test-WSMan to see if WinRM works, but old habits die hard. By default, on certain profiles, and on certain versions of the operating system, the Ping command is disabled. It really makes life difficult in the early hours of the morning when I tend to forget these sorts of things. So, I like to explicitly ensure that Ping is permitted through Windows Firewall. Once I have done this, and a machine does not respond to Ping, I know I need to do something else.
Unfortunately, while I can use the Get-NetFireWallRule cmdlet to retrieve information about scope and status of a firewall rule, it does not display what the actual rule itself is or does. This means that, for example, I cannot use Get-NetFireWallRule to retrieve a firewall rule and use it as a pattern when it comes to creating a new rule. In addition, it means that I cannot use the GUI tool to create a new firewall rule, use the Get-NetFireWallRule cmdlet to obtain the actual rules themselves, and then use that to create a new rule. Get-NetFireWallRule is useful for auditing but not for system configuration.
To create a new firewall rule that permits the Ping command, I first import the NetSecurity module. Next, I use the New-NetFirewallRule cmdlet to create the new firewall rule. The problem with this is that I basically have to know what I am doing … specifically. If, for example, I do not know that a Ping is ICMPv4 protocol, and specifically ICMPType 8, then I have no chance of creating a new firewall rule. This is where the GUI tool is a bit more friendly—rather than having to look up the ICMPTypes, they are available through the ICMP type page. This is shown here.
Here again, even the GUI tool does not actually list the ICMP type. So to get this information, I need to either already know it (Hey, I wrote a book on Network Monitoring and Analysis), or I need to look it up by using Ping.
I recommend using the Windows PowerShell cmdlet to create the firewall rule, and then inspecting the rule in the Windows Firewall with Advanced Security tool. Here is the rule I came up with to permit Ping on network interfaces with the ANY profile. (Note that I could use DOMAIN or PRIVATE profiles as well.)
New-NetFirewallRule -Name Allow_Ping -DisplayName "Allow Ping"`
-Description "Packet Internet Groper ICMPv4" `
-Protocol ICMPv4 -IcmpType 8 -Enabled True -Profile Any -Action Allow
The first thing I need to do is to find all of my computers running Windows Server 2012 and Windows 8. I created a specific filter for the Get-ADComputer cmdlet that returns only these types of computers. I also specify Admin credentials to the Get-Credential cmdlet. This is shown here.
Import-Module NetSecurity, ActiveDirectory
$cred = Get-Credential -Credential iammred\administrator
$cn = Get-ADComputer -Properties operatingsystem -Filter `
"Operatingsystem -like 'windows 8 *' -OR OperatingSystem -like '* 2012 *'"
Now, I create a CIM session to each of these computers. When I do this, I specify the name of the computer and the credentials to use to make the connection. I do not worry if computers are offline when calling the command because it only connects with online machines. It simplifies the code. This appears here.
$CIM = New-CimSession -ComputerName $cn.name -Credential $cred
Next, I use the same New-NetFirewallRule command I used before—only this time I add that I want to use the CIM sessions in the $cim variable. Here is the code.
-Protocol ICMPv4 -IcmpType 8 -Enabled True -Profile Any -Action Allow `
Because I already have the CIM sessions in the $CIM variable, I can use that with the Get-NetFirewallRule cmdlet to verify that the remote servers and workstations have received the new firewall rule. This command is shown here.
Get-NetFirewallRule -DisplayName "Allow Ping" -CimSession $cim |
Select PSComputerName, name, enabled, profile, action |
The command and the associated output are shown here.
I also want to verify that the Pings themselves will take place. Now, remember that the Get-ADComputer command returned some computers that were offline. But the $CIM variable contains CIM sessions to each computer that is obviously online. Unfortunately, the Test-Connection cmdlet does not accept a CIM session object, but that does not matter because it does accept an array of computer names. With auto array expansion, I can get the computer names from the variable containing all of the CIM sessions easily. Here is the command to which I arrived.
Test-Connection -ComputerName $cim.computername -BufferSize 15 -Count 1
The command and associated output are shown here.
PS C:\> Test-Connection -ComputerName $cim.computername -BufferSize 15 -Count 1
Source Destination IPV4Address IPV6Address
------ ----------- ----------- -----------
EDLT DC2 192.168.0.102
EDLT DC3 192.168.0.103
EDLT DC4 192.168.0.104
EDLT EDLT 192.168.3.228 fe80::bd2d:5283:5572:5e77%19
EDLT HYPERV2 192.168.0.46
EDLT HYPERV3 192.168.0.43
EDLT SQL1 192.168.0.150
EDLT WDS1 192.168.0.152
EDLT WEB1 192.168.0.54
Sweet, it worked! Join me tomorrow when I will talk about more way-cool Windows PowerShell stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
For powershell v2 machines, invoke a built in window:
netsh.exe advfirewall firewall add rule name = '$($_.name)' dir=$($_.dir) action=$($_.action) enable=$($_.enable) profile=$($_.profile) localip=$($_.localip) remoteip=$($_.remoteip) protocol=$($_.protocol) edge=$($_.edge) localport=$($_.localport) remoteport=$($_.remoteport)
@PowerShell Nub yes, you can use NetSh to work with firewall rules when you do not have access to Windows 8 and Windows PowerShell 3.0. Thanks for adding this.
Is it work for windows 2008 R2? I get an error when "Import-Module NetSecurity"
Import-Module : The specified module 'NetSecurity' was not loaded because no valid module file was found in any module
At line:1 char:14
+ Import-Module <<<< NetSecurity
+ CategoryInfo : ResourceUnavailable: (NetSecurity:String) [Import-Module], FileNotFoundException
+ FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand
Nope... them mentioned module is part of powershell 3. but you can installa PS 3 onto a 2008 R2 along with the .NET Framework 4 :)