Using Python To Manipulate IP Addresses and Perform CIDR Calculations
Using Python To Manipulate IP Addresses and Perform CIDR Calculations
You can get more information about this module with the help command from the
Python interpreter:
is the class that represents and manipulates single IPv4 addresses:
IPv4Address
The class represents an IPv4 address or network. To create these objects in
Python, the module provides some basic factory functions:
import ipaddress
from ipaddress import IPv4Address, IPv4Network, IPv4Interface
After you create an IPv4/IPv6 object, you can get a lot information from the
class, for example, whether it is a multicast address or a private address, the
prefix length, and netmask.
In the following screenshot, we can see the methods that are used to check these
use cases:
From Python 3.3, the best way to check whether an IPv6 or IPv4 address is
correct is to use the Python standard library module, ipaddress.
Check out https://docs.python.org/3/library/ipaddress.html for the complete documentation.
If you're using Python 3.3 or later, you can use the ipaddress module to validate
the IP address:
>>> import ipaddress
>>> ipaddress.ip_address('127.0.0.1')
IPv4Address('127.0.0.1')
>>> ipaddress.ip_address('500.500.0.1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.7/ipaddress.py", line 54, in ip_address
address)
ValueError: '500.500.0.1' does not appear to be an IPv4 or IPv6 address
In this example, we use this method to validate both IPv4 and IPv6. You can find
the following code in the validate_ip_address.py file:
!/usr/bin/env python3
import ipaddress
import sys
try:
ip = ipaddress.ip_address(sys.argv[1])
print('%s is a correct IP%s address' % (ip, ip.version))
except ValueError:
print('address/netmask is invalid: %s' % sys.argv[1])
except:
print('Usage : %s ip' % sys.argv[0])
This module will provide several classes and factory functions for working with
both IPv4 and IPv6 versions.
IP network objects
Let's import the ipaddress module and define a net4 network:
>>> import ipaddress
>>> net4 = ipaddress.ip_network('10.0.1.0/24')
Now, we can find some useful information, such as netmask and the
network/broadcast address, of net4:
>>> net4.netmask
IP4Address(255.255.255.0)
The netmask properties of net4 will be displayed as an IP4Address object. If you are
looking for its string representation, then you can call the str() method, as shown
here:
>>> str(net4.netmask)
'255.255.255.0'
Similarly, you can find the network and the broadcast addresses of net4 by using
the following code:
>>> str(net4.network_address)
10.0.1.0
>>> str(net4.broadcast_address)
10.0.1.255
We can get the number of addresses net4 can hold with the following command:
>>> net4.num_addresses
256
So, if we subtract the network and the broadcast addresses, the total available IP
addresses will be 254. We can call the hosts() method on the net4 object. This will
produce a Python generator, which will supply all the hosts as IPv4Address objects:
>>> net4.hosts()
>>> <generator object _BaseNetwork.hosts at 0x02F25FC0>
>>> all_hosts = list(net4.hosts())
>>> len(all_hosts)
254
>>> print(all_hosts)
>>> [IPv4Address('10.0.1.1'), IPv4Address('10.0.1.2'), IPv4Address('10.0.1.3'), IPv4Address('10.0.1.4'
Subnetting in Python
Another use case is an IP subnetting application, which gives you the required IP
subnets based on required network size or amount of networks per location. We
can also find the subnet information from the IPv4Network objects, as follows:
>>> net4.subnets()
<generator object _BaseNetwork.subnets at 0x02F2C0C0>
>>> subnets = list( net4.subnets())
>>> subnets
[ IPv4Network('10.0.1.0/25'), IPv4Network('10.0.1.128/25') ]
The ipaddress module includes many functions to create subnets and supernets;
for example, we can use these methods to check whether a network overlaps
with another:
>>> ipnet = ipaddress.IPv4Network("10.2.0.0/16")
>>> list(ipnet.subnets())
[IPv4Network('10.2.0.0/17'), IPv4Network('10.2.128.0/17')]
Any IPv4Network object can tell, which is the opposite of the subnet by looking at its
parent supernet:
>>> net4.supernet()
IPv4Network('10.0.0.0/23')
Network interface objects
In the ipaddress module, we have a convenient class to represent an interface's IP
configuration in detail: IPv4Interface. It takes an arbitrary address and behaves
like a network address object:
>>> import ipaddress
>>> eth0 = ipaddress.IPv4Interface('192.168.0.1/24')
>>> eth0.ip
IPv4Address('192.168.0.1')
>>> eth0.with_prefixlen
'192.168.0.1/24'
>>> eth0.with_netmask
'192.168.0.1/255.255.255.0'
>>> eth0.network
IPv4Network('192.168.0.0/24')
>>> eth0.is_private
True
>>> eth0.is_reserved
False
>>> eth0.is_multicast
False
>>>
As you can see, a network interface, eth0, with the IPv4Address class, has been
defined. It has some interesting properties, such as IP and network address. In
the same way as the network objects, you can check whether the address is
private, reserved, or multicast.
IP address objects
In this example, the loopback interface is defined with the 127.0.0.1 IP address. As
you can see, the is_loopback property returns True:
>>> loopback = ipaddress.IPv4Interface('127.0.0.1')
>>> loopback.is_private
True
>>> loopback.is_reserved
False
>>> loopback.is_multicast
False
>>> loopback.is_loopback
True
The IP address classes have many more interesting properties. You can perform
some arithmetic and logical operations on those objects. For example, we can
check whether an IP address is part of a network.
Suppose you have a CIDR network address, such as 192.168.0.0/24, and you want
to generate a range of all the IP addresses that it represents (192.168.0.1 to
192.168.0.254). The ipaddress module can be easily used to perform such
calculations:
>>> import ipaddress
>>> net = ipaddress.ip_network('192.168.0.0/24')
>>> net
IPv4Network('192.168.0.0/24')
>>> for a in net:
... print(a)
...
192.168.0.1
192.168.0.2
192.168.0.3
...
192.168.0.254
In this example, we are using the ip_network method from the ipaddress module to
generate a range of all the IP addresses that represent the network.
import ipaddress as ip
CLASS_C_ADDR = '192.168.0.0'
try:
network = ip.ip_network(net_addr)
except:
raise Exception("Failed to create network object")
The following is the execution of the previous script for some masks and
the C class IP address, 192.168.0.0: