Python: How to validate an IP Address with a CIDR notation (import socket)
Question:
I’ve got a script which is using argparse to pull flags from the command line and using socket to validate an IP Address. So far it works if I’m just using the standard IPv4 X.X.X.X format. What I want to do is validate an IP Address that includes a CIDR notation. How can I modify my bit of code to validate the 2-digit integer in the CIDR field (ie: 192.168.2.1/32)
import argparse
import socket
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--ipaddr")
args = parser.parse_args()
# Validate IP Address Given in (-i) argparse
try:
s = socket.inet_aton(args.ipaddr)
except socket.error:
print ""
print("Bad IP Address entered")
print ""
sys.exit()
Answers:
Python 3
There is an ipaddress module that may do the job.
The constructor of the class Ip4Network
handles both 255.255.255.255
and 255.255.255.255/32
(and also IPv6 format, with Ip6Network
)
So you may add in your code
import ipaddress
and create an Ip4Network
with the code:
try:
ip_addr = ipaddress.ip_network(args.ipaddr)
except ValueError:
# handle bad ip
Than, continue with your code on the socket:
socket.inet_aton(str(ip_addr))
you have only to convert it in a string.
Python 2.7
The ipaddress
must be installed from the repository (py2-ipaddress
) and has some issue between str
and bytearray
interpretation of string (refer here)
So it works in my experiments if you do:
ipaddress.ip_address(bytearray('192.168.1.1'))
ipaddress.ip_network(u'10.0.0.0/24')
Additional remarks
CIDR
To complete the aswer considering also the comment made by @Dave:
-
ipaddress.ip_network
validates against ip address, not CIDR notation.
-
ipaddress.ip_network
validates against networks, not CIDR notation.
-
To validate a CIDR notation with host bits set you must set the strict
input parameter to False
to avoid raise a ValueError('%s has host bits set' % self)
.
ipaddress.ip_network('192.168.1.1/24', False)
# IPv4Network('192.168.1.0/24')
Turn off strict mode and use ip_network
ipaddress.ip_network('192.168.1.10/24',False)
IPv4Network('192.168.1.10/24')
I’ve got a script which is using argparse to pull flags from the command line and using socket to validate an IP Address. So far it works if I’m just using the standard IPv4 X.X.X.X format. What I want to do is validate an IP Address that includes a CIDR notation. How can I modify my bit of code to validate the 2-digit integer in the CIDR field (ie: 192.168.2.1/32)
import argparse
import socket
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--ipaddr")
args = parser.parse_args()
# Validate IP Address Given in (-i) argparse
try:
s = socket.inet_aton(args.ipaddr)
except socket.error:
print ""
print("Bad IP Address entered")
print ""
sys.exit()
Python 3
There is an ipaddress module that may do the job.
The constructor of the class Ip4Network
handles both 255.255.255.255
and 255.255.255.255/32
(and also IPv6 format, with Ip6Network
)
So you may add in your code
import ipaddress
and create an Ip4Network
with the code:
try:
ip_addr = ipaddress.ip_network(args.ipaddr)
except ValueError:
# handle bad ip
Than, continue with your code on the socket:
socket.inet_aton(str(ip_addr))
you have only to convert it in a string.
Python 2.7
The ipaddress
must be installed from the repository (py2-ipaddress
) and has some issue between str
and bytearray
interpretation of string (refer here)
So it works in my experiments if you do:
ipaddress.ip_address(bytearray('192.168.1.1'))
ipaddress.ip_network(u'10.0.0.0/24')
Additional remarks
CIDR
To complete the aswer considering also the comment made by @Dave:
-
ipaddress.ip_network
validates against ip address, not CIDR notation. -
ipaddress.ip_network
validates against networks, not CIDR notation. -
To validate a CIDR notation with host bits set you must set the
strict
input parameter toFalse
to avoid raise aValueError('%s has host bits set' % self)
.ipaddress.ip_network('192.168.1.1/24', False) # IPv4Network('192.168.1.0/24')
Turn off strict mode and use ip_network
ipaddress.ip_network('192.168.1.10/24',False)
IPv4Network('192.168.1.10/24')