Search CIDR subnet ranges with powershell

Rich Rumble
Rich Rumble used Ask the Experts™
on
I'd like to be able to search for an IP's within CIDR ranges/list, and output the information around that IP's CIDR file.
Very similar to this EE question https://www.experts-exchange.com/questions/29127048/Excel-CIDR-IP-Address-Overlap-Formula-Check-for-CIDR-IP-Address-Overlap.html

This is what I envision...
CIDR.csv
CIDR, Subnet_Name
10.0.0.0/24, Guest Network
10.10.0.0/23, Production
10.8.0.0/22, Telco
10.69.69.0/24, BoomChickaWowWow

Open in new window


.\findip.ps1 10.0.0.22
    Found: 10.0.0.22 - Guest Network 10.0.0.0/24

.\findip.ps1 10.8.0.123, 10.69.69.68, 10.1.2.3
   Found: 10.8.0.123 - Telco 10.8.0.0/22
   Found: 10.69.69.68 - BoomChickaWowWow
   Not Found: 10.1.2.3

FindIp would look inside the cidr.csv and then expand the CIDR's and seqrch for matches within.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Rather than re-invent the wheel, try this script. Just find a method to that suites you for iterating through the subnets.

function IPInRange {
    [cmdletbinding()]
    [outputtype([System.Boolean])]
    param(
        # IP Address to find.
        [parameter(Mandatory,
                   Position=0)]
        [validatescript({
            ([System.Net.IPAddress]$_).AddressFamily -eq 'InterNetwork'
        })]
        [string]
        $IPAddress,

        # Range in which to search using CIDR notation. (ippaddr/bits)
        [parameter(Mandatory,
                   Position=1)]
        [validatescript({
            $IP   = ($_ -split '/')[0]
            $Bits = ($_ -split '/')[1]

            (([System.Net.IPAddress]($IP)).AddressFamily -eq 'InterNetwork')

            if (-not($Bits)) {
                throw 'Missing CIDR notiation.'
            } elseif (-not(0..32 -contains [int]$Bits)) {
                throw 'Invalid CIDR notation. The valid bit range is 0 to 32.'
            }
        })]
        [alias('CIDR')]
        [string]
        $Range
    )

    # Split range into the address and the CIDR notation
    [String]$CIDRAddress = $Range.Split('/')[0]
    [int]$CIDRBits       = $Range.Split('/')[1]

    # Address from range and the search address are converted to Int32 and the full mask is calculated from the CIDR notation.
    [int]$BaseAddress    = [System.BitConverter]::ToInt32((([System.Net.IPAddress]::Parse($CIDRAddress)).GetAddressBytes()), 0)
    [int]$Address        = [System.BitConverter]::ToInt32(([System.Net.IPAddress]::Parse($IPAddress).GetAddressBytes()), 0)
    [int]$Mask           = [System.Net.IPAddress]::HostToNetworkOrder(-1 -shl ( 32 - $CIDRBits))

    # Determine whether the address is in the range.
    if (($BaseAddress -band $Mask) -eq ($Address -band $Mask)) {
        $true
    } else {
        $false
    }
}

Open in new window


Source/Credit
Most Valuable Expert 2018
Distinguished Expert 2018
Commented:
Returns proper objects, entries not found in a range are written to the Warning stream by default; can be suppressed using -WarningAction SilentlyContinue, or you can use -IncludeNotFound, which will create an object as for the ones found, but obviously with the Subnet and CIDR columns empty.
Accepts pipeline input as well.
[CmdletBinding()]
Param(
	[Parameter(Position=0, ValueFromPipeline=$true)]
	[IPAddress[]]$IPAddress,
	[Switch]$IncludeNotFound
)
Begin {
	Function ConvertTo-DecimalAddress([IPAddress]$IPAddress) {
		$bytes = $IPAddress.GetAddressBytes()
		[array]::Reverse($bytes)
		[BitConverter]::ToUInt32($bytes, 0)
	}
	$data = Import-Csv -Path '.\CIDR.csv' | ForEach-Object {
		$firstAddress = ConvertTo-DecimalAddress -IPAddress $_.CIDR.Split('/')[0]
		$hosts = [math]::Pow(2, (32 - $_.CIDR.Split('/')[1])) - 1
		$_ | Select-Object -Property *, @{n='FirstAddress'; e={$firstAddress}}, @{n='LastAddress'; e={$firstAddress + $hosts}}
	}
}
Process {
	$IPAddress | ForEach-Object {
		$address = ConvertTo-DecimalAddress -IPAddress $_
		If ($row = $data | Where-Object {($_.FirstAddress -le $address) -and ($address -le $_.LastAddress)}) {
			$_ | Select-Object -Property @{n='IPAddress'; e={$_.ToString()}}, @{n='CIDR'; e={$row.CIDR}}, @{n='Subnet_Name'; e={$row.Subnet_Name}}
		} Else {
			If ($IncludeNotFound) {
				$_ | Select-Object -Property @{n='IPAddress'; e={$_.ToString()}}, CIDR, Subnet_Name
			} Else {
				Write-Warning "IP address $($_.ToString()) not found"
			}
		}
	}
}

Open in new window

Rich RumbleSecurity Samurai
Top Expert 2006

Author

Commented:
Wow, you guys make this look easy! oBdA is getting the majority of the points, the solution worked great! I've got a /8 with 6k different CIDR subnets/names and this searches through all of it in few seconds! I will have some follow up questions soon, keep an eye out :)
-rich
Rich RumbleSecurity Samurai
Top Expert 2006

Author

Commented:

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial