Monthly Archive

Networking

Network adapter Index

A few years ago I wrote a post about setting the IP metric on a connection - https://richardspowershellblog.wordpress.com/2012/01/01/changing-ip-connection-metric/

 

I was recently asked if the Index’s associated with network adapters were consistent acros machines. The answer – unfortunately- is no they’re not as a rule.

 

I used the function from the original post

function Test-IPmetric {
    Get-WmiObject -Class Win32_NetworkAdapter -Filter "AdapterType = 'Ethernet 802.3'" |
    foreach {
        Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter “Index=$($_.DeviceId)” |
        Select-Object Description, Index, IPEnabled, IPConnectionMetric
    }
}

to view the index

 

The Index property from Win32_NetworkAdapaterConfiguration is identical to the DeviceId from the Win32_NetworkAdapater class for a given network adapter.

 

if you try the function on a number of machines you’ll see that Index numbers assigned by Windows aren’t consistent.  My test VMs (Hyper-V) all seem to have the same index numbers assigned but I always create my VMs and add network adapters in the same way.

 

I wouldn’t rely on a particular index being assigned to a given network adapter – always pull the data and test

IP Default Gateways by cmdlet

Following my recent post on setting the default gateway by using the Win32_NetworkAdapterConfiguration CIM class here’s how you do it using the networking cmdlets

Discover your adapters

Get-NetAdapter

 

Check the default gateway for an adapter

Get-NetIPConfiguration -InterfaceIndex 12 | select InterfaceIndex, IPv4Address, IPv4DefaultGateway

 

Set the default gateway

New-NetRoute -InterfaceIndex 12  -DestinationPrefix '0.0.0.0/0' -NextHop '10.10.54.1'

 

This isn’t as intuitive as using the CIM class

Check the setting

£> Get-NetIPConfiguration -InterfaceIndex 12

InterfaceAlias       : Ethernet
InterfaceIndex       : 12
InterfaceDescription : Microsoft Hyper-V Network Adapter
NetProfile.Name      : Manticore.org
IPv4Address          : 10.10.54.100
IPv6DefaultGateway   :
IPv4DefaultGateway   : 10.10.54.1
DNSServer            : 10.10.54.201

 

To remove the default gateway

Remove-NetRoute -InterfaceIndex 12 -NextHop '10.10.54.1' -Confirm:$false

 

If you leave off –Confirm you’ll be prompted to confirm the action on the active and persistent stores i.e. twice.

 

All of the above cmdlets are part of the NetTCPIP module available on Windows 8/Server 2012 and later.

IP Default Gateways

When you configure the IP Address on a network adapter you also have to set the default gateway if you want the machine to communicate with machines on other subnets.

 

One way you can do this is through the SetGateways method of Win32_NetworkAdapterConfiguration

$class = Get-CimClass -ClassName Win32_NetworkAdapterConfiguration

$class.CimClassMethods['SetGateWays'].Parameters

Name                  CimType Qualifiers                         ReferenceClassName
----                  ------- ----------                         ------------------
DefaultIPGateway  StringArray {ID, In, MappingStrings}
GatewayCostMetric UInt16Array {ID, In, MappingStrings, Optional}

 

Notice you need to supply the information as arrays so:

$dgw = @('10.10.54.1')
$gcm = @([uint16]2)

 

The default for the metric is 1. The metric is supplied as an unsigned 16 bit integer

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "Index=2"  | Invoke-CimMethod –MethodName  SetGateWays -Arguments @{DefaultIPGateway = $dgw; GatewayCostMetric = $gcm}

 

To change the gateway simply overwrite the values via another call to SetGateways()

 

To completely remove the gateway information you need to set the value of the gateway to be the same as the IP address on the adapter

$dgw = @('10.10.54.200')
$gcm = @([uint16]1)

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "Index=2"  | Invoke-CimMethod –MethodName  SetGateWays -Arguments @{DefaultIPGateway = $dgw; GatewayCostMetric = $gcm}

 

Leaving the metric as 1 will cause no harm

 

Next time I’ll show how to perform the same actions with the networking cmdlets

Modifying MAC address

 

Another question on the forum brought up an interesting point. User want adapter name and mac address

PS> Get-NetAdapter | select Name, MacAddress

Name                         MacAddress
----                         ----------
WiFi                         28-18-78-D0-05-11
Bluetooth Network Connection 28-18-78-D0-05-12

 

but wanted to remove the hyphens in the mac address so tried

PS> Get-NetAdapter | select Name, MacAddress | foreach {$_.MacAddress -replace '-',''}
281878D00511
281878D00512

 

This doesn’t work because the foreach cmldet only knows to put put the new string when the hyphens have been replaced in the mac address. The name is effectively filtered out.

 

The answer is to use a calculated field in select-object like this

PS> Get-NetAdapter | select Name, @{N='MacAddress'; E={$_.MacAddress -replace '-',''}}

Name                         MacAddress
----                         ----------
WiFi                         281878D00511
Bluetooth Network Connection 281878D00512

 

N = Name and E= Expression though they are usually shorten for brevity as shown

Parsing ipconfig /displaydns with regular expressions

In yesterdays post I used a series of split operations to parse the strings produced by ipconfig /displaydns

 

Regular expressions should give a more power full way to perform this task. Not being a big fan of regular expressions I tend not to use them but for the sake of experimentation I thought I’d try and figure out a set of regex to use.

 

This is as far as I’ve got

 

$props = [ordered]@{
  RecordName = ""
  RecordType = ""
  Section    = ""
  TimeToLive = 0
  DataLength = 0
  Data       = ""
}

$recs = @()

$cache = ipconfig /displaydns
for($i=0; $i -le ($cache.Count -1); $i++) {
if ($cache[$i] -like '*Record Name*'){
    $rec = New-Object -TypeName psobject -Property $props
    $rec.RecordName = $cache[$i] -replace "(\s*\w*){2}(\s\.){5}(\s\:\s)", ""
    $rec.Section = $cache[$i+4] -replace "\s*\w*(\s\.){7}(\s\:\s)", ""
    $rec.TimeToLive = $cache[$i+2] -replace "(\s*\w*){3}\s(\s\.){4}(\s\:\s)", ""
    $rec.DataLength = $cache[$i+3] -replace "(\s*\w*){2}(\s\.){5}(\s\:\s)", ""
   
    $irec = ($cache[$i+5] -split ": ")
    $rec.RecordType = ($irec[0].TrimStart() -split ' ')[0]
    $rec.Data = $irec[1]

    $recs += $rec
}
else {
    continue
}
}

$recs | Format-Table –AutoSize

 

I still need to work out how to process the data and record type using regular expressions

Parsing ipconfig /displaydns

 

A recent question on the forum asked how you could get the contents on Windows 7 machines and earlier.

On later machines – Windows 8 and above -  its easy because you can use Get-DnsClientCache from the DnsClient module. This module is based on CIM classes that aren’t present on Windows 7 and earlier systems.

 

You can use ipconfig /displaydns to display the data but it looks like this

Record Name . . . . . : ns-nw.noaa.gov
Record Type . . . . . : 1
Time To Live  . . . . : 81966
Data Length . . . . . : 4
Section . . . . . . . : Additional
A (Host) Record . . . : 161.55.32.2

 

so you need to parse the strings into a format that you can work with. 

 

This is one solution

 

$props = [ordered]@{
  RecordName = ""
  RecordType = ""
  Section    = ""
  TimeToLive = 0
  DataLength = 0
  Data       = ""
}

$recs = @()

$cache = ipconfig /displaydns
for($i=0; $i -le ($cache.Count -1); $i++) {
if ($cache[$i] -like '*Record Name*'){
    $rec = New-Object -TypeName psobject -Property $props
    $rec.RecordName = ($cache[$i] -split -split ": ")[1]
    $rec.Section = ($cache[$i+4] -split -split ": ")[1]
    $rec.TimeToLive = ($cache[$i+2] -split -split ": ")[1]
    $rec.DataLength = ($cache[$i+3] -split -split ": ")[1]
   
    $irec = ($cache[$i+5] -split ": ")
    $rec.RecordType = ($irec[0].TrimStart() -split ' ')[0]
    $rec.Data = $irec[1]

    $recs += $rec
}
else {
    continue
}
}

$recs | Format-Table –AutoSize

Create an ordered hash table of output properties and an empty array to hold the results.

 

Get the output of  ipconfig /displaydns into $cache which will be an array of strings

Loop through $cache

 

if the record is like *Record Name*' then process that record and the next five records to give the results.  The actual data record is split twice to give the record type and the data – otherwise you’ll have to translate the numeric values in the Record Type line.

 

The results are put into an object which is added to the output array.

 

Continue looping through $cache until you meet the next line with a Record Name or end of file.

 

Finally display the results.

 

This works but is messy – I’m going to investigate alternatives

IPAM: 2 Reading data

Once you have your IPAM server configured you can start to read the data its collected.

If you are working against a remote IPAM server than you need to create a CIM session to that machine before doing anything else.

$cs = New-CimSession -ComputerName W12R2SUS

 

You can discover the domain you’re working against

£> Get-IpamDiscoveryDomain -CimSession $cs | fl

Name           : manticore.org
DiscoverDc     : True
DiscoverDns    : True
DiscoverDhcp   : True
PSComputerName : W12R2SUS

The IPAM server configuration

£> Get-IpamConfiguration -CimSession $cs | fl

Version            : 6.3.0.1
Port               : 48885
ProvisioningMethod : Manual
GpoPrefix          :
HMACKey            : System.Security.SecureString
PSComputerName     : W12R2SUS

 

The servers – DHCP, DNS and DCs that IPAM is aware of:

£> Get-IpamServerInventory -CimSession $cs

RecommendedAction   : IPAM Access Unblocked
ManageabilityStatus : Managed
IPAMAccessStatus    : Unblocked
ServerType          : {DC, DNS, DHCP}
ServerName          : server02
Name                : server02.Manticore.org
DnsSuffix           : Manticore.org
DomainName          : manticore.org
ServerStatus        : NoChange
DataRetrievalStatus : Completed
IPv4Address         : {10.10.54.201}
IPv6Address         :
PSComputerName      : W12R2SUS

 

The address space

£> Get-IpamAddressSpace -CimSession $cs

Name                           : Default
Type                           : ProviderAddressSpace
Owner                          :
Description                    : Default Provider IP Address Space
AssociatedProviderAddressSpace :
Tenant                         :
VMNetwork                      :
IsolationMethod                :
Ipv4PercentageUtilized         : 3.44827586206896
Ipv6PercentageUtilized         : 0
CustomConfiguration            :
PSComputerName                 : W12R2SUS

 

Individual subnets

£> Get-IpamSubnet -CimSession $cs -AddressFamily IPv4

Name                 : 10.10.54.0/24
NetworkId            : 10.10.54.0/24
NetworkType          : NonVirtualized
Overlapping          : False
NetworkSite          :
VmmLogicalNetwork    :
ProviderAddressSpace : Default
CustomerAddressSpace :
VlanId               :
Owner                :
PSComputerName       : W12R2SUS

 

and the address ranges for those subnets

£> Get-IpamRange -CimSession $cs -AddressFamily IPv4

Overlapping      : False
NetworkID        : 10.10.54.0/24
StartIPAddress   : 10.10.54.2
EndIPAddress     : 10.10.54.30
ManagedByService : MS DHCP
ServiceInstance  : server02.Manticore.org
NetworkType      : NonVirtualized
Owner            :
PSComputerName   : W12R2SUS

IPAM: 1 Installation and configuration

IPAM stands for IP Address Management. It’s a feature in Windows Server 2012 R2 that enables you manage your DHCP and DNS servers as a whole rather than at the individual service or server level.

 

Installation of IPAM follows the standard approach for any Windows feature. Note that you can install IPAM on a Domain Controller but it won’t configure. IPAM is designed to be installed on a member server.

Full details on deploying IPAM server are available from here https://technet.microsoft.com/en-us/library/hh831353.aspx

 

I’m not going to run through the full deployment and configuration – just point out some issues and where you can use PowerShell to make things easier.

 

Once the IPAM feature is installed you have to provision the IPAM server. There isn’t a separate MMC for IPAM admin – you use Server Manager.  Provisioning an IPAM server can be done manually or by GPO.  Manual seemed best for lab/experiment/initial set up as can't swap from GPO to manual. You can use Windows Internal Database (WID) or SQL Server – I used WID.

 

You then need to configure your DHCP servers, DNS servers and domain controllers. This involves a number of group membership changes, firewall rule changes and a registry setting.

 

Create a group called IPAMUG and add the IPAN server into it.

New-ADGroup -Name IPAMUG -DisplayName IPAMUG -SamAccountName IPAMUG    -Description 'IPAM management group' -GroupCategory Security -GroupScope Universal

Add-ADGroupMember -Identity IPAMUG -Members (Get-ADComputer -Identity W12R2SUS)

 

Add IPAMUG to a number of groups

Add-ADGroupMember -Identity 'Event Log Readers' -Members (Get-ADGroup -Identity IPAMUG)

Add-ADGroupMember -Identity 'DHCP Users' -Members (Get-ADGroup -Identity IPAMUG)

Add-ADGroupMember -Identity 'DNSAdmins' -Members (Get-ADGroup -Identity IPAMUG)

 

I also found I had to add the IPAM server to the domain Administrators group to get the DNS data to come through.

 

Modify some firewall rules

$cs = New-CimSession -ComputerName W12R2SCDC01

Enable-NetFirewallRule  -DisplayName 'Remote Service Management (RPC)' -CimSession $cs -PassThru
Enable-NetFirewallRule  -DisplayName 'Remote Service Management (NP-In)' -CimSession $cs -PassThru
Enable-NetFirewallRule  -DisplayName 'Remote Service Management (RPC-EPMAP)' -CimSession $cs -PassThru

Get-NetFirewallRule -DisplayGroup 'Remote Service Management' -CimSession $cs |
ft  DisplayName, Enabled, Direction,Profile –a

 

There are a bunch of firewall rules that need setting. You can find the full list in the TechNet documentation.

For DHCP servers create an audit share

 

New-SmbShare -Name dhcpaudit -Path 'C:\Windows\System32\dhcp' -ReadAccess 'manticore\IPAMUG'
Set-SmbShare -Name dhcpaudit -Description 'DHCP audit share for IPAM' -Force

## restart DHCP service
Get-Service -Name DHCPServer | Restart-Service -PassThru

 

Enable event log monitoring on the DNS servers

$csd = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\DNS Server' -Name CustomSD |
select -ExpandProperty CustomSD
$ipamsid = (Get-ADComputer -Identity W12R2SUS | select -ExpandProperty SID).value
$csd = $csd + "(A;;0x1;;;$ipamsid)"
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\DNS Server' -Name CustomSD -Value $csd –PassThru

 

I also had to manually add the IPAMUG group into the security permissions for the DNS servers. Didin’t seem to be a way to automate that bit.

 

IPAM has a PowerShell module – IpamServer – which contains lots of cmdlets:

Add-IpamAddress
Add-IpamAddressSpace
Add-IpamBlock
Add-IpamCustomField
Add-IpamCustomFieldAssociation
Add-IpamCustomValue
Add-IpamDiscoveryDomain
Add-IpamRange
Add-IpamServerInventory
Add-IpamSubnet
Disable-IpamCapability
Enable-IpamCapability
Export-IpamAddress
Export-IpamRange
Export-IpamSubnet
Find-IpamFreeAddress
Get-IpamAddress
Get-IpamAddressSpace
Get-IpamAddressUtilizationThreshold
Get-IpamBlock
Get-IpamCapability
Get-IpamConfiguration
Get-IpamConfigurationEvent
Get-IpamCustomField
Get-IpamCustomFieldAssociation
Get-IpamDatabase
Get-IpamDhcpConfigurationEvent
Get-IpamDiscoveryDomain
Get-IpamIpAddressAuditEvent
Get-IpamRange
Get-IpamServerInventory
Get-IpamSubnet
Import-IpamAddress
Import-IpamRange
Import-IpamSubnet
Invoke-IpamGpoProvisioning
Invoke-IpamServerProvisioning
Move-IpamDatabase
Remove-IpamAddress
Remove-IpamAddressSpace
Remove-IpamBlock
Remove-IpamConfigurationEvent
Remove-IpamCustomField
Remove-IpamCustomFieldAssociation
Remove-IpamCustomValue
Remove-IpamDhcpConfigurationEvent
Remove-IpamDiscoveryDomain
Remove-IpamIpAddressAuditEvent
Remove-IpamRange
Remove-IpamServerInventory
Remove-IpamSubnet
Rename-IpamCustomField
Rename-IpamCustomValue
Set-IpamAddress
Set-IpamAddressSpace
Set-IpamAddressUtilizationThreshold
Set-IpamBlock
Set-IpamConfiguration
Set-IpamCustomFieldAssociation
Set-IpamDatabase
Set-IpamDiscoveryDomain
Set-IpamRange
Set-IpamServerInventory
Set-IpamSubnet
Update-IpamServer

Now I’ve got my IPAM server up and running its time to see what I can do with it

Creating NIC team without knowing the team members

I was asked how to create a NIC team only using the 1GB adapters without knowing how many 1gb NICs were on the server.

 

I think this should solve the problem

 

New-NetLbfoTeam -TeamMembers (Get-NetAdapter | where Speed -ge 1gb | select -ExpandProperty Name) -Name MyTeam

 

Use New-NetLbfoTeam to create the team. The team member names are generated by

 

Get-NetAdapter | where Speed -ge 1gb | select -ExpandProperty Name

 

By putting that statement in parentheses as the value for the –TeamMembers parameter the results are used as the value for the parameter.  Shouldn’t matter now how many NICs or what they are called.  You can modify the filter criteria as required.

DNS client settings

Following yesterdays post there are a couple of other cmdlets worth looking at if you want to dig into the DNS settings on your client machines.

Get-DnsClient wil show you the DNS relsted settings for all of your network interfaces by default.  To investigate a single interface

 

£> Get-DnsClient -InterfaceAlias vEthernet* | fl

InterfaceAlias                     : vEthernet (External01)
InterfaceIndex                     : 20
ConnectionSpecificSuffix           :
ConnectionSpecificSuffixSearchList : {}
RegisterThisConnectionsAddress     : True
UseSuffixWhenRegistering           : False

InterfaceAlias                     : vEthernet (Internal01)
InterfaceIndex                     : 16
ConnectionSpecificSuffix           :
ConnectionSpecificSuffixSearchList : {}
RegisterThisConnectionsAddress     : True
UseSuffixWhenRegistering           : False

 

You can also see the DNS servers a particular interface will use:

£> Get-DnsClientServerAddress -InterfaceAlias vEthernet*

InterfaceAlias               Interface Address ServerAddresses
                             Index     Family
--------------               --------- ------- ---------------
vEthernet (External01)              20 IPv4    {192.168.0.1}
vEthernet (External01)              20 IPv6    {}
vEthernet (Internal01)              16 IPv4    {}
vEthernet (Internal01)              16 IPv6    {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3}