How can I check if an ip is in a network in Python?
This article shows you can do it with socket
and struct
modules without too much extra effort. I added a little to the article as follows:
import socket,struct
def makeMask(n):
"return a mask of n bits as a long integer"
return (2L<<n-1) - 1
def dottedQuadToNum(ip):
"convert decimal dotted quad string to long integer"
return struct.unpack('L',socket.inet_aton(ip))[0]
def networkMask(ip,bits):
"Convert a network address to a long integer"
return dottedQuadToNum(ip) & makeMask(bits)
def addressInNetwork(ip,net):
"Is an address in a network"
return ip & net == net
address = dottedQuadToNum("192.168.1.1")
networka = networkMask("10.0.0.0",24)
networkb = networkMask("192.168.0.0",24)
print (address,networka,networkb)
print addressInNetwork(address,networka)
print addressInNetwork(address,networkb)
This outputs:
False
True
If you just want a single function that takes strings it would look like this:
import socket,struct
def addressInNetwork(ip,net):
"Is an address in a network"
ipaddr = struct.unpack('L',socket.inet_aton(ip))[0]
netaddr,bits = net.split('/')
netmask = struct.unpack('L',socket.inet_aton(netaddr))[0] & ((2L<<int(bits)-1) - 1)
return ipaddr & netmask == netmask
check if an IP is within a range of CIDR in Python
You can't really do string comparisons on a dot separated list of numbers because your test will simply fail on input say 1.1.99.99
as '9'
is simply greater than '2'
>>> '1.1.99.99' < '1.1.255.255'
False
So instead you can convert the input into tuples of integers through comprehension expression
def convert_ipv4(ip):
return tuple(int(n) for n in ip.split('.'))
Note the lack of type checking, but if your input is a proper IP address it will be fine. Since you have a 2-tuple of IP addresses, you can create a function that takes both start and end as argument, pass that tuple in through argument list, and return that with just one statement (as Python allows chaining of comparisons). Perhaps like:
def check_ipv4_in(addr, start, end):
return convert_ipv4(start) < convert_ipv4(addr) < convert_ipv4(end)
Test it out.
>>> ip_range = ('1.1.0.0', '1.1.255.255')
>>> check_ipv4_in('1.1.99.99', *ip_range)
True
With this method you can lazily expand it to IPv6, though the conversion to and from hex (instead of int) will be needed instead.
How to check an IP address is within a range of two IPs in Python?
For changing the ip format so that we can compare
def convert_ipv4(ip):
return tuple(int(n) for n in ip.split('.'))
This function will return True or False if the ip is within range or not
def check_ipv4_in(addr, start, end):
return convert_ipv4(start) < convert_ipv4(addr) < convert_ipv4(end)
ip_range = ('1.1.0.0', '1.1.255.255')
print(check_ipv4_in('1.1.99.99', *ip_range))
It will print 'true' in this case as the function returns True in this case
How do you determine if an IP address is private, in Python?
Check out the IPy module. If has a function iptype()
that seems to do what you want:
>>> from IPy import IP
>>> ip = IP('127.0.0.0/30')
>>> ip.iptype()
'PRIVATE'
How to check if an IP is contained in a network with python?
Using Python 3.3+ ipaddress
>>> import ipaddress
>>> ipaddress.ip_address('10.40.0.1') in ipaddress.ip_network('10.40.0.0/24')
True
>>> ipaddress.ip_address('10.40.2.1') in ipaddress.ip_network('10.40.0.0/24')
False
There's also backport of ipaddress
.
Using ipaddr
>>> import ipaddr
>>> ipaddr.IPAddress('10.40.0.1') in ipaddr.IPNetwork('10.40.0.0/24')
True
>>> ipaddr.IPAddress('10.40.2.1') in ipaddr.IPNetwork('10.40.0.0/24')
False
Find if IP in set of ip addresses and ip networks
One way would be to use the ipaddress
module to build a set
of IPv4Address
instances:
>>> from ipaddress import *
>>> from itertools import *
>>>
>>> p = {'127.0.0.1', '138.56.76.02', '192.4.2.0/24', '29.24.48.80', ...}
>>>
>>> all_hosts = set(chain.from_iterable(IPv4Network(n) for n in p))
>>>
>>> IPv4Address('192.4.2.4') in all_hosts
True
>>> IPv4Address('29.24.48.80') in all_hosts
True
>>> IPv4Address('29.24.48.81') in all_hosts
False
This takes advantage of the fact that constructing an IPv4Network from just an address (with no mask) creates a network with just that address in it. It also uses the feature that iterating an IPv4Network
gives you each host in turn.
The all_hosts
set will be slow to build and large in memory if p is large or the netmasks contain many hosts. However, after that, checking if an IP address is in the set is fast (O(1) on average).
All this still works if p
already contains IPv4Network
and IPv4Address
instances.
Check if IP is in network on Python3
What you are describing as a list is actually a tuple.
First, when I ran your code I did not receive the error you are getting
ValueError: b'82.148.47.64' does not appear to be an IPv4 or IPv6 address
Instead I received the following
raise ValueError('%s has host bits set' % self)
ValueError: 1.1.6.0/20 has host bits set
Is this the error your are actually receiving? If so, this is how to properly correct it.
Referenced from ipaddress module Defining Networks:
By default, attempting to create a network object with host bits set will result in ValueError being raised. To request that the additional bits instead be coerced to zero, the flag strict=False can be passed to the constructor:
This is because the host bits are set and will need to be coerced to zero, as the documentation states above. Pass the following flag strict=False to the constructor.
For example.
subnet = ip_network(network[0], strict=False)
Also, in your ips contained in your tuple need only to be formatted to a string.
For example.
ips = ((8888, 'customer', '2.8.4.64', '8888*200')
OR the following will be presented to you.
'ValueError: b'2.8.4.64' does not appear to be an IPv4 or IPv6 address'
The full working code.
from ipaddress import ip_network, ip_address
networks = (('1.1.6.0/20',), ('2.8.2.0/19',), ('7.2.2.0/19',), ('2.2.0.0/19',))
ips = ((8888, 'customer', b'2.8.4.64', '8888*200'),(8888, 'customer', b'1.1.6.3', '8888*201'), (8888, 'customer', b'122.223.159.3', '8888*202'))
straglers = list()
for ip in ips:
exclude = 0
for network in networks:
subnet = ip_network(network[0], strict=False)
print(ip_address(ip[2].decode('utf-8')))
print(subnet)
if ip_address(ip[2].decode('utf-8')) in subnet:
exclude = 1
if exclude == 0:
straglers.append([ip[3],ip[2],ip[1]]) # extension, customer_ip, company
print(straglers)
Related Topics
How to Use Python to Execute a Curl Command
Reference List Item by Index Within Django Template
Easy Way of Finding Decimal Places
Change the Colors Within Certain Range to Another Color Using Opencv
How to Use Youtube-Dl from a Python Program
Merge Multiple Column Values into One Column in Python Pandas
Adding Meta-Information/Metadata to Pandas Dataframe
How to Run Python Script Without Typing 'Python ...'
Pandas: Filtering Multiple Conditions
Best Way to Format Integer as String with Leading Zeros
Fill Username and Password Using Selenium in Python
Asyncio.Sleep() VS Time.Sleep()
Creating Spark Data Structure from Multiline Record
How Many Concurrent Requests Does a Single Flask Process Receive