How to Manipulate IP Addresses in Python using ipaddress Module

Abdou Rockikz · 19 nov 2019

Abdou Rockikz · 5 min read · Python Standard Library

In this tutorial, you will learn how you can use ipaddress module to work with IP addresses in Python, network engineers use this module so often as it provides handy functions and classes that handles various tasks that are related to IP addresses, including checking whether two hosts belong to the same subnet, iterating over all hosts of a subnet, retrieving broadcast addresses of a particular subnet, and much more.

Related: How to Make a Network Scanner using Scapy in 5 Minutes.

We don't need to install anything is this module comes built-in and it was introduced in Python 3.3, so if you have Python 3.3+ (and I'm sure you do), you're good to go!

Let's start by IPv4Address class:

import ipaddress
# initialize an IPv4 Address
ip = ipaddress.IPv4Address("192.168.1.1")

Now this ip object represent a single IP address, we can check whether it is a global IP address (not private) and whether it is a link local:

# print True if the IP address is global
print("Is global:", ip.is_global)

# print Ture if the IP address is Link-local
print("Is link-local:", ip.is_link_local)

Output:

Is global: False
Is link-local: False

You can also use ip.is_reserved and ip.is_multicast to check whether this IP address is in the list of reserved IP and multicast addresses respectively.

You can perform addition and subtraction on IP addresses:

# next ip address
print(ip + 1)

# previous ip address
print(ip - 1)

You guessed it, adding an IP by 1 means it is the next IP address, subtracting by 1 means the previous IP address, here is the output:

192.168.1.2
192.168.1.0

Write dir(ip) to discover various methods and attributes you can use.

Now that you have a basic understanding of IPv4Address object, let's dive into handling IPv4Network objects:

# initialize an IPv4 Network
network = ipaddress.IPv4Network("192.168.1.0/24")

Now this network object represents an IPv4 network, the /24 thing is CIDR notation, it indicates that leading 24 bits of the total 32 bits of the IP address are used to identify the network portion of the address, that means in this case, "192.168.1.x" is network portion (3x8 = 24 bits), and only the last octet "x.x.x.0" is the host portion.

You can retrieve the network mask of this network:

# get the network mask
print("Network mask:", network.netmask)

Output:

Network mask: 255.255.255.0

The network mask is just another format (maybe older) for expressing and representing the network portion of the address, in this case 255.255.255.0 means that the leading 24 bits which are filled with 1's (255 is 11111111 in binary) indicates the network part of the address (same as /24 notation).

Here is how you can get the broadcast address of the network:

# get the broadcast address
print("Broadcast address:", network.broadcast_address)

Output:

Broadcast address: 192.168.1.255

Printing the number of hosts that belongs to this network:

# print the number of IP addresses under this network
print("Number of hosts under", str(network), ":", network.num_addresses)

Output:

Number of hosts under 192.168.1.0/24 : 256

A total of 256 hosts (including the subnet and broadcast addresses) are available under this network, here is how you can iterate over all of them:

# iterate over all the hosts under this network
print("Hosts under", str(network), ":")
for host in network.hosts():
    print(host)

This will print all valid host IP addresses that range from 192.168.1.1 to 192.168.1.254.

You can also get the subnets of this network:

# iterate over the subnets of this network
print("Subnets:")
for subnet in network.subnets(prefixlen_diff=2):
    print(subnet)

Output:

Subnets:
192.168.1.0/26
192.168.1.64/26
192.168.1.128/26
192.168.1.192/26

network.subnets() method returns the subnets which join to make the current subnet as list of IPv4Network objects, prefixlen_diff parameter is an integer that indicates the amount the prefix length should by increased by, I set this to 2 so i can get /26 subnets.

You can also get the supernet:

# get the supernet of this network
print("Supernet:", network.supernet(prefixlen_diff=1))

This will return the supernet containing the current network, here is the output:

Supernet: 192.168.0.0/23

Finally, you can test whether a network overlaps another network:

# tell if this network is under (or overlaps) 192.168.0.0/16
print("Overlaps 192.168.0.0/16:", network.overlaps(ipaddress.IPv4Network("192.168.0.0/16")))

Output:

Overlaps 192.168.0.0/16: True

It returned True, as 192.168.1.1/24 subnet is under 192.168.0.0/16 network.

Alright, we are done for this tutorial, you can explore this module by check their official documentation for more functions and classes for IPv4 and also IPv6 addresses that are really handy for network engineers and Python programmers that wish to develop network applications.

Read Also: How to Make a DNS Spoof attack using Scapy in Python.

Happy Coding ♥

View Full Code
Sharing is caring!


Read Also





Comment panel

   
Comment system is still in Beta, if you find any bug, please consider contacting us here.