Monday, July 9, 2012

Enabling PING echo in Server 2012 with PowerShell

Once again, lets use the new PowerShell cmdlets that ship in the box with Server 2012.

The Server 2008 way of enabling PING to echo involved netsh.

netsh advfirewall firewall add rule name=”Allow Ping” protocol=icmpv4 dir=in action=allow 

Mind you, netsh is still in Server 2012 and this command works, but it is the old way of doing things, lets look forward.

Actually, lets run that netsh command on Server 2012 and see what we get – explore the assumptions of this netsh command.

Get-NetFirewallRule –Name “Allow Ping”

image

Hmm.  No Firewall rules found that match.  But in my netsh command I set name=”Allow Ping”, what gives?

Well, if you list all the rules out, you discover that netsh sets the DisplayName property, not the name property of the rule.  It creates a random GUID for the Name.  And, if you try New-NetFirewallRule you discover that –DisplayName is required but –Name is not.  (the things you learn).

image

Okay, enough discovery.

Let’s create the same rule using PowerShell in Server 2012

New-NetFirewallRule –DisplayName “Allow Ping” –Direction Inbound –Action Allow –Protocol icmpv4 –Enabled True

Now, the really nifty thing is that I can really quickly disable the same rule and turn PING echoes back off.

Set-NetFirewallRule –DisplayName “Allow Ping” –Enabled False

The rule remains, but it is simply disabled so I don’t need to create it again.  And I can turn it back on when I need.

And, to remove the rule entirely:

Remove-NetFirewallRule –DisplayName “Allow Ping”

Thursday, July 5, 2012

Hyper-V Extensible Switch unified tracing

I have been spending some quality time with the Hyper-V Networking features and I ran into a bit of a problem that I needed to unwind.

I was using the new Network Virtualization feature and I was encapsulating the traffic. 

This is where one host gets the packet from a VM, wraps it in an envelope, sends it to the host where the target VM is, unwraps its, and sends it to the receiving VM.

They also support IP Rewrite, which can be through of as NAT’ing.

I was having a problem where I needed to determine if things were working properly.  I had no way to tell without some type of tracing.

This is where Unified Tracing comes in.  You enable it on the Hyper-V Server and tell it which module and you get this highly detailed ETL format back out (use the latest Network Monitor to view).  I can see the traffic leave the VM, then hit the Network Virtualization module, then leave the switch and so on. 

I can capture the Windows Network Virtualization events by executing the following:

Netsh trace start provider=Microsoft-windows-wnv level=5

I can capture switch events and packets by executing the following:

Netsh trace start provider=Microsoft-Windows-Hyper-V-VmSwitch capture=yes capturetype=vmswitch

I capture both together (as you can only have one trace active at a time) with the following:

Netsh trace start provider=Microsoft-windows-wnv level=5 provider=Microsoft-Windows-Hyper-V-VmSwitch capture=yes capturetype=vmswitch

Now, what I did was I took my synchronization script and I combined that with this tracing into the following coordinating trace capture script:

# Coordinated Network tracing of Windows Network Virtualization
# Run this on both hosts.
# this will run for 3 minutes and then stop.  This should be enough time to do your test.  Change as you need.


# Only one trace can be executing at a time, you must choose one.
$selection = Read-Host -Prompt "Enter the trace number `
1 - WNV Events`
2 - VM packets and switch events`
3 - Both 1 and 2`
"


Get-date
# wait until the next 5 minute even increment
Do {
    # square up near the whole minute mark to "synchronize watches"
    Start-Sleep ( 60 - (Get-Date -Format ss) )
    [string]$nowMinute = Get-Date -Format mm
} until ( $nowMinute -match ".[0,5]" )

Get-Date

"Begin Repro"


switch ( $selection ) {
    1 {
        # capture WNV events
        $trace = Netsh trace start provider=Microsoft-windows-wnv level=5
    }
    2 {
        # capture switch events and packets
        $trace = Netsh trace start provider=Microsoft-Windows-Hyper-V-VmSwitch capture=yes capturetype=vmswitch
    }
    3 {
        # capture both providers together
        $trace = Netsh trace start provider=Microsoft-windows-wnv level=5 provider=Microsoft-Windows-Hyper-V-VmSwitch capture=yes capturetype=vmswitch
    }
}

Start-sleep -Seconds 120  #Two minutes of this is plenty of noise to pick through.

"Stopping Trace"
Get-Date

# Stop the trace
Netsh trace stop


foreach ( $i in $trace ) {
    if ( $i.Contains("Trace File") ) {
        $tracePath = $i.Split(" ")
        $file = $tracepath[($tracepath.Length - 1)]
    }
}
# Convert the ETL to TXT
Netsh trace convert $file


# The ETL can be viewed using Netmon 3.4 or newer.

Wednesday, June 20, 2012

Server 2012 Install-WindowsFeature Net-Framework-Features fail. Use the source, Luke

Let go.

The force is strong on this one.

Trust your feelings.

I don’t know if you have noticed or not.  But if you attempt to install the .Net 3.5 on Server 2012 it always fails.

This seems to have been particularly troublesome to application installers that ‘just expect it to work’ and fail instead.    Then you end up here, desperately trying to figure out how to install .Net 3.5.

If you wan to see the error that these installers are tossing; simply open a PowerShell windows and attempt to install .Net 3.5 using install- (or add- ) Windows Feature:

image

A nice big fat failure.  But you think, this always worked before.  Server 2008 / R2 / SP1 this worked without a hitch or problem.  It was built-in. What gives?

The issue is in the detail of that error:  Use the “source” option to specify the location of the files…

Well, seems that the files are not there, at least for .Net 3.5 they are not installed to the local WinSxS source location when the OS is installed.  (Ever wondered how you can add features after install?  ‘Sources’)

Looking around a bit, you will eventually find it.  On the installation CD / ISO.  So that becomes your source path.  Insert the DVD or mount the ISO to your VM and use the following:

Add-WindowsFeature –name NET-Framework-Features –source D:\sources\sxs

The “D:” in my case is the drive letter of the CD drive of my VM.

image

Tuesday, June 19, 2012

Generating random passwords with PowerShell, rehash

In the recent password issue with LinkedIn.  The ArsTechnica report really makes it is evident that passwords alone are not enough.  DarkReading also has a good story on this.

Even passwords believed to be secure were hacked within hours or a day or two.  It is simply an issue of computing power.  Contrast that against what the human brain can memorize in regards to complex passwords. 

I was (and still am) a proponent of pass phrases as you could make a longer password and substitute characters and it was easier to remember.  But alas, it is just a password – and that must be recognized.

It is obvious that two-factor is the real way to go.  As Coding Horror elaborated on a while back, and I implemented after there was an attempt to hack my Facebook account (thank you for login alerts).  You know, it really isn’t that big of an inconvenience or problem.

But, I digress.

So, to blog a bit more about using PowerShell to do useful things – like generating a password string.

You can find all kinds of references to doing this.  Go search and pick your favorite:

http://letmebingthatforyou.com/?q=powershell%20generate%20random%20passwords

From that, I chose two.  I quick one liner, and a more complex script.

From PowerShell.com there are a few Generate Random Password Power Tips.  It is obviously a popular topic.

The first:

function Get-RandomPassword {
    param(
        $length = 10,
        $characters =

        'abcdefghkmnprstuvwxyzABCDEFGHKLMNPRSTUVWXYZ123456789!"§$%&/()=?*+#_'
    )
    # select random characters
    $random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
    # output random pwd
    $private:ofs = ""
    [String]$characters[$random]
}

The second:

-join ([Char[]]'abcdefgABCDEFG0123456&%$' | Get-Random -count 20)

That one is pretty good if you just want to generate a password on the fly within a script.

The third:

function Get-RandomPassword {
    param(
        $length = 11,
        $characters = 'abcdefghkmnprstuvwxyzABCDEFGHKLMNPRSTUVWXYZ123456789!"§$%&/()=?*+#_'
    )
    # select random characters
    $random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
    # output random pwd
    $private:ofs = ""
    [String]$characters[$random]
}

function Randomize-Text {
    param(
        $text
    )
    $anzahl = $text.length -1
    $indizes = Get-Random -InputObject (0..$anzahl) -Count $anzahl
    $private:ofs = ''
    [String]$text[$indizes]
}

function Get-ComplexPassword {
    $password = Get-RandomPassword -length 6 -characters 'abcdefghiklmnprstuvwxyz'
    $password += Get-RandomPassword -length 2 -characters '#*+)'
    $password += Get-RandomPassword -length 2 -characters '123456789'
    $password += Get-RandomPassword -length 4 -characters 'ABCDEFGHKLMNPRSTUVWXYZ'
    Randomize-Text $password
}

This last one enforces password policy by guaranteeing a count of specific character types.  Why they left out ‘0’ I don’t know.  Also notice that the calls to Get-RandomPassword at the end constrains the special characters that are used / returned.  So if you have a web site that can’t handle special characters or it cannot handle specific ones you can constrain that here. 

I also found the blog of Erwin Wendland and his Create-RandomPassword Function for creating strong passwords.  This last one I would call a bit more like C#.

Tuesday, June 5, 2012

Synchronizing PowerShell script execution on multiple machines

I originally thought to call this “synchronizing watches” but since I am not changing system time I thought it might be misleading.  This post is all about synchronizing script execution on two different machines.

Some folks would use a central client and workflows (PowerShell v3) or PowerShell remoting to execute a script on remote machines at the same time.  Possibly even executing each one as a job so they happen at the same time. 

It also allows me to launch the script on server A and then move to the other side of the lab to launch its script and then begin the repro (or switch the monitor on the KVM).  I know that as long as they share a time service I can be confident in when the tracing began on the remote machine.

In my case I want to execute the script on each machine at the console.  My reasoning is that; the machines are not in the same domain making security messy, or I don’t want to modify firewall rules, or I am capturing network traffic and just don’t want the extra noise to filter through.

Here is my scenario: 

  • I have multiple servers (a large, distributed application)
  • Different things are happening on each server
  • I want to enable a network trace at the same time (to have nicely correlated logs)
  • The systems already have a common time source (the OS handles that after all)
  • I need to manually trigger the reproduction of the bug after the tracing starts, or I need to trigger some event prior to the tracing beginning
  • I only have two hands and two feet

Here is the synchronization snip at the beginning of my script:

Do {
    Start-Sleep ( 60 - (Get-Date -Format ss) )
    
    [string]$nowMinute = Get-Date -Format mm
} until ( $nowMinute[($nowMinute.Length - 1)] -eq "0" -or $nowMinute[($nowMinute.Length - 1)] -eq "5" )

The first thing that I do I describe as squaring up.  I invoke a Start-Sleep but I want to sleep until the end of the current minute, no longer.

Start-Sleep ( 60 - (Get-Date -Format ss) )

You could do this as two lines as well (or three if you like):

$secToZero = 60 - (Get-Date -Format ss)

Start-Sleep $secToZero

Then I get the current minute and evaluate it to the nearest 5 minute block.

I chose the 5 minute mark because it is easy to evaluate to (if the number ends in 0 or 5 it divides by 5).  I cast the returned integer to a string as well, so I can get that last digit.

[string]$nowMinute = Get-Date -Format mm

*Notice that if you use “MM” instead of “mm” you get the Month.

I do my math evaluation at the end of the Until.  Notice the –or between the 0 and 5 after the –eq.  That is important to force the evaluation against both numbers.

Here is where personal preference sets in.  I dreamed up three different ways to handle the evaluation in the Until block.

The first is a very literal evaluation of the second digit in the Seconds to see if it equals “0” or “5”.  the entire last line looks like this:

} until ( $nowMinute[($nowMinute.Length - 1)] -eq "0" -or $nowMinute[($nowMinute.Length - 1)] -eq "5" )

It is the ($nowMinute.Length –1) that puts us at position 1 ( position begins counting at 0) to perform the evaluation.  The position indicator for the array is the square brackets [].

Another way to handle this is through the PowerShell way to handle a Regular Expression (or a pattern match – a nice article on that is here.)

Based on that article I can keep my –or and simply indicate the second digit this way:

} until ( $nowMinute -match ".0" -or $nowMinute -match ".5" )

Or, I can do it more like a regular expression and state in a shorter line that the second digit can match either 0 or 5.  That looks like this:

} until ( $nowMinute -match ".[0,5]" )

The end result is all the same.  Much of the technique is all about personal preference.