Using the wrong bind order for multihomed servers can cause serious problems. Applications not working, network segments flooded with unneccesary traffic and even security leaks are some of the dangers.

That’s why I’ve created a Powershell script that checks all your servers for you. Let me explain how it works:

The binding order is store in the following registry key:

HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage

It contains a multi-string value Bind such as this one:

DeviceNetBT_Tcpip_{A0344E82-4E65-47A2-92FF-B3183A181473}

DeviceNetBT_Tcpip_{C34D5A39-DA8D-4D58-82D4-099098D5501C}

What we are interested in, is to identify each TCP/IP interface in this list. We can identify them by correlating the identifier (or key) between the curly brackets {} to an IP address. We find all relevant information in the following registry key:

SYSTEMCurrentControlSetServicesTcpipParametersInterfaces

It contains subkeys named after the identifiers of the different TCP/IP interfaces, with a multi-string  value IPAddress which contains the IP addresses set on this interface.

So let’s read the second collection of registry keys and values first, and create a collection of objects representing the interfaces, having properties representing the identifier and the IP address:

$registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $serverName)         # Open remote HKLM key

$baseKey2 = $registry.OpenSubKey(“SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces”)

$myCol = @()

$NICS = $baseKey2.GetSubKeyNames()                    # Set of interfaces

ForEach ($NIC in $NICS)

{

$myObj = “” | Select-Object Key, IP         # Create object for relation between identifier and IP address

$key = $baseKey2.OpenSubKey(“$NIC”)

$myObj.Key = $key.name.split(“{“)[1].trimend(“}”)         # Get identifier of interface without brackets

$myObj.IP = $key.GetValue(“IPAddress”)         # Get IP address of interface

$myCol += $myObj         # Create collection of interface objects

}

Nice. Now we have the $myCol variable holding a collection of objects like so:

PS D:Scripts> $myCol

Key                                                                               IP

—                                                                                  –

1B68A2DD-B093-4E12-A347-CED975434F12      {0.0.0.0}

313D4DA6-B0A6-41B6-B34D-97C89A3E0D65     {10.2.0.112}

A0344E82-4E65-47A2-92FF-B3183A181473        {10.1.0.112}

C34D5A39-DA8D-4D58-82D4-099098D5501C     {0.0.0.0}

Now let’s read the binding order:

$baseKey1 = $registry.OpenSubKey(“SYSTEM\CurrentControlSet\Services\Tcpip\linkage”)

$bindorder = $baseKey1.GetValue(“Bind”)

That’s easy! Now to match the correct IP address to the second object in the $bindorder array:

$wantedboundkey = $bindorder[$index].split(“{“)[1].trimend(“}”)         # Get identifier of …th TCP/IP interface in binding order

$wantedbound = $myCol | Where {$_.Key -eq $firstboundkey}         # Find matching interface in collection

$wantedbound.IP        # Return matching IP address

And there you have it!

PS D:Scripts>$wantedbound.IP

10.2.0.112

Below is the entire script that queries Active Directory for computers and runs the above script (defined as a function).

You should be able to figure out how it works.

Enjoy!

$outputFile = “D:Scriptsoutput.txt”                        # Default output path

function Get-BoundIP

{

param([string]$serverName, [Int]$index)

$registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $serverName)        # Open remote HKLM key

If ($registry)

{

$baseKey1 = $registry.OpenSubKey(“SYSTEM\CurrentControlSet\Services\Tcpip\linkage”)

$bindorder = $baseKey1.GetValue(“Bind”)

$baseKey2 = $registry.OpenSubKey(“SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces”)

$myCol = @()

$NICS = $baseKey2.GetSubKeyNames()        # Set of interfaces

ForEach ($NIC in $NICS)

{

$myObj = “” | Select-Object Key, IP        # Create object for relation between identifier and IP address

$key = $baseKey2.OpenSubKey(“$NIC”)

$myObj.Key = $key.name.split(“{“)[1].trimend(“}”)        # Get identifier of interface

$myObj.IP = $key.GetValue(“IPAddress”)        # Get IP address of interface

$myCol += $myObj        # Create collection of interface objects

}

$wantedboundkey = $bindorder[$index].split(“{“)[1].trimend(“}”)        # Get identifier of …th interface in binding order

$wantedbound = $myCol | Where {$_.Key -eq $wantedboundkey}        # Find matching interface in collection

$wantedbound.IP        # Return matching IP address

}

}

Write-Host “Grabbing server names …”

$servers = Get-QADComputer -SizeLimit 0 -SearchRoot “OU=Servers,DC=example,DC=com” | Sort-Object Name        # Get all servers from AD

$myCollection = @()

ForEach ($server in $servers)

{

Write-Host “Processing server” $server.name

$myObject = “” | Select-Object Name, FirstIP, SecondIP        # Create object for output organization

$myObject.Name = $server.name        # Set server name

$myObject.FirstIP = Get-BoundIP $server.name 0       # Run function to get first bound IP address

$myObject.SecondIP = Get-BoundIP $server.name 1

$myCollection += $myObject        # Build collection of objects

}

$output = $myCollection | Format-Table -AutoSize        # Format output

# Create output

If ((Test-Path $outputFile) -eq $False)                # If the output file does not exist

{

Write-Host “Creating output file …”

$creatingOutputFile = New-Item $outputFile -ItemType File                # Create output file

}

Write-Host “Writing output to file …”

$output | Out-File -FilePath $outputFile -Force                # Output file is overwritten with new output

Write-Host “Launching output file ($outputFile) …”

Invoke-Item $outputFile

»crosslinked«

Tagged with:
 

11 Responses to Check NIC bind order

  1. //o// says:

    Hi,

    Just small detail, but as the Trim method does accept more then one character, this method of removing the curly braces might be a bit more clear

    $key.name.trim(‘{}’)

    Enjoy,
    Groeten //o//

  2. b1 says:

    I see this script gives a listing of the bind orders, but is it possible to modify the script to automatically change the binding order of the interfaces?

  3. Suresh says:

    Hi:
    This is a great script. Thank you very much.
    One improvement to take care of conditions where some servers have one NIC and another has two is to initialize the variable after each iteration:
    $myObject.FirstIP = “”
    $myObject.SecondIP = “”
    after your statement:
    $myObject = “” | Select-Object Name, FirstIP, SecondIP

  4. Nice script, did you notice that all backslashes appear as interpreted, when you read your post? c:\path becomes c:path and and SYSTEM\CurrentControlSet becomes SYSTEMCurrentControlSet.

  5. William says:

    This script will not produce accurate results in some cases.

    The Bind list is ordered without account for whether the interface is active/assigned IP or a virtual/loopback adapter.

    Best to get the Bind values and then compare them against a WMI query that filters out the loopback adapters (servicename = msloop), ipenabled != ‘false’ and those without IP’s (ipaddress != 0.0.0.0).

    Using the WMI query as validation for the Bind list pulling out the first valid Bind entry.

    That’s what I’m rolling in to prod anyway since it’s accurate, but thanks for showing the path.

  6. Jorge 's Quest For Knowledge! : Changing The Binding Order Of Network Connections From The Command-Line says:

    […] network bindings. How are you going to achieve that then? You could use the procedure as mentioned here. However, you could also use the tool available here. This tool was created by a Microsoft […]

  7. Sparky says:

    Hello,

    I just want to say that you can check binding order through command “ipconfig /all” and in which order NICs are same binding order these NICs have.

  8. […] Now imagine, you are using the other available installation option, also known as Server Core. As you may know, Server Core does not provide, that does not provide a GUI such as the Network Connections Control Panel to change network bindings. How are you going to achieve that then? You could use the procedure as mentioned here. […]

  9. Larry says:

    Hi PeetersOnline,

    I tried the BIND order script but when I try to create this variable:

    $wantedboundkey = $bindorder[$index].split(“{“)[1].trimend(“}”)

    I receive error:

    PS C:\Users\larryh> $wantedboundkey = $bindorder[$index].split(“{“)[1].trimend(“}”) # Get identifier of .
    th TCP/IP interface in binding order

    Index operation failed; the array index evaluated to null.
    At line:1 char:30
    + $wantedboundkey = $bindorder[ <<<< $index].split("{")[1].trimend("}") # Get identifier of .th TCP/IP interfac
    e in binding order
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

    Can you take a look?

  10. admin says:

    Oops, I see now the slashes in SYSTEMCurrentControlSetServicesTcpiplinkage disappeared in the post. I’ll try to fix the post.
    Hugo

Leave a Reply