SysAdmin Basics - Working With IP Addresses

Whether you like it or not, at some point in your career you will be working with IPs. I recently ran into a challenge at work with variable length subnet masks that inspired this post. I needed to brush off some old networking skills and got to play with a little PowerShell along the way. With that in mind, let’s get into it.

The Good Stuff: A couple of tricks to make working with IPs a little less painful.

Approach

There’s two common approaches I see most people take when working with IPs. By far the most popular is to use Regex. I was never a big Regex guy, but I’ve been trying to get better. I’m fortunate enough to work with some incredibly talented people. One of whom, is an absolute monster when it comes to Regex. It’s damn impressive when you see the language levered to it’s full potential. My personal gripe with Regex is that its hard to read… That said, it’s capabilities are undeniable.

The next not so often talked about method is to leverage the [ipaddress] class. This class gives us a lot of freebies since the .Net team did the hard stuff for us. Plus if you combine that with a little bitwise math, you can recreate subnetting in PowerShell.

Validating An IP Address

Ok let’s start with the most important one. Is this a valid IP?

Regex

I did a quick search on Google for “IP regex”. The below pattern is the most commonly accepted answer.

^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$

Obviously…. Now we could use this pattern to check if we’re working with a valid IP. Something like this.

$ipPattern = '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$'
$AddressToTest = '192.168.0.1'

if($AddressToTest -match $ipPattern)
{
    #Some code for a valid IP Here
}
else
{
    #Some error handling here
}

IPAddress Type

I like using the IPAddress type for this one. What you do is leverage the -As operator to cast the IP. If the IP cast works, -As returns an IPaddress object. Take a look at this example to see it in action.

'192.168.0.1' -as [ipaddress]

Output:

Address            : 16820416
AddressFamily      : InterNetwork
ScopeId            :
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv4MappedToIPv6 : False
IPAddressToString  : 192.168.0.1

The best part is that if we use an invalid IP address, -As will not throw an error. Instead it returns null. Try running the below example in your shell, you shouldn’t get anything back.

'10000.08.x' -as [ipaddress]

What this means for us, is that we can rewrite the first example as follows:

$AddressToTest = '192.168.0.1'

if($AddressToTest -as [ipaddress])
{
    #Some code for a valid IP Here
}
else
{
    #Some error handling here
}

Finding The Default Gateway

The default gateway is the door from your network to the next. Sometimes, you only have an IP address and need to guess at the default gateway. Usually the gateway has an address like your IP except with the last octet of .1. This is especially true if you have a /24 or 255.255.255.0 subnet mask.

If you know you need to replace the last octet with a 1, Regex is the perfect tool. Take a look at the below snippet to set a default gateway using Regex.

$address = '192.168.0.24'
$defaultGW = $address -replace '\d{1,3}$','1'

$defaultGW

Output:

192.168.0.1

Here’s where it starts getting good. We can combine Regex and the IPAddress class to work with subnets other than /24. Let’s pretend you have a /18 or 255.255.192.0. What we could do is leverage some bitwise math to find the network ID. Don’t worry it’s not as bad as it sounds.

$address = [ipaddress]'10.153.67.25'
$subnetMask = [ipaddress]'255.255.192.0'

[ipaddress]$network = $address.Address -band $subnetMask.Address
$network.IPAddressToString

Output:

10.153.64.0

This address and the subnet mask together identify the entire network. Once we know this, we can use regex to set the default gateway to the first usable IP.

Finding The Broadcast Address

On a network, the broadcast address is a reserved IP that sends a message to the entire subnet. We find the broadcast address again using bitwise math. This time we are going to use the IP address and the wildcard mask. If your unfamiliar with a wildcard mask, it’s the exact inverse of a subnet mask. Like a subnet mask identifies the network, the wildcard mask identifies the host. Here’s the snippet in PowerShell to find the broadcast address.

$ipaddress = [ipaddress]'192.168.0.34'
$wildCardMask = [ipaddress]'0.0.0.255'

[ipaddress]$broadCast = $ipaddress.Address -bor $wildCardMask.Address
$broadCast

Output:

Address            : 4278233280
AddressFamily      : InterNetwork
ScopeId            :
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv4MappedToIPv6 : False
IPAddressToString  : 192.168.0.255

Converting To Binary String

The first thing I wrote for this article was the ConvertTo-BinaryAddress function. In school I had an amazing network instructor that really drilled the basics into us. Thanks to this, it’s still a lot easier for me to visual subnetting when I can see the binary. Here’s the function in action.

PS > ConvertTo-BinaryAddress -Address 192.168.0.23

11000000.10101000.00000000.00010111

PS > ConvertTo-BinaryAddress -Address 255.255.255.0

11111111.11111111.11111111.00000000

PS > ConvertTo-BinaryAddress -Address 0.0.0.255

00000000.00000000.00000000.11111111

Wrapping Up

That’s all for today. Got any cool tricks you use with IPs? Leave a comment and let us know.

Written on July 17, 2017