In Python, what is the best way to determine if an IP address (e.g., \'127.0.0.1\'
or \'10.98.76.6\'
) is on a private network? The code does not s
You can check that yourself using
http://tools.ietf.org/html/rfc1918 and http://tools.ietf.org/html/rfc3330. If you have 127.0.0.1 you just need to &
it with the mask (lets say 255.0.0.0
) and see if the value matches any of the private network's network address. So using inet_pton you can do: 127.0.0.1 & 255.0.0.0 = 127.0.0.0
Here is the code that illustrates that:
from struct import unpack
from socket import AF_INET, inet_pton
def lookup(ip):
f = unpack('!I',inet_pton(AF_INET,ip))[0]
private = (
[ 2130706432, 4278190080 ], # 127.0.0.0, 255.0.0.0 http://tools.ietf.org/html/rfc3330
[ 3232235520, 4294901760 ], # 192.168.0.0, 255.255.0.0 http://tools.ietf.org/html/rfc1918
[ 2886729728, 4293918720 ], # 172.16.0.0, 255.240.0.0 http://tools.ietf.org/html/rfc1918
[ 167772160, 4278190080 ], # 10.0.0.0, 255.0.0.0 http://tools.ietf.org/html/rfc1918
)
for net in private:
if (f & net[1]) == net[0]:
return True
return False
# example
print(lookup("127.0.0.1"))
print(lookup("192.168.10.1"))
print(lookup("10.10.10.10"))
print(lookup("172.17.255.255"))
# outputs True True True True
another implementation is to compute the int values of all private blocks:
from struct import unpack
from socket import AF_INET, inet_pton
lookup = "127.0.0.1"
f = unpack('!I',inet_pton(AF_INET,lookup))[0]
private = (["127.0.0.0","255.0.0.0"],["192.168.0.0","255.255.0.0"],["172.16.0.0","255.240.0.0"],["10.0.0.0","255.0.0.0"])
for net in private:
mask = unpack('!I',inet_aton(net[1]))[0]
p = unpack('!I',inet_aton(net[0]))[0]
if (f & mask) == p:
print lookup + " is private"
If you want to avoid importing a module you can just apply a simple regex:
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'
I find this in cuckoo.There is no need to install new modules.Just import two built-in modules: socket and struct. And use function below.
def _is_private_ip(self, ip):
"""Check if the IP belongs to private network blocks.
@param ip: IP address to verify.
@return: boolean representing whether the IP belongs or not to
a private network block.
"""
networks = [
"0.0.0.0/8",
"10.0.0.0/8",
"100.64.0.0/10",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"192.0.0.0/24",
"192.0.2.0/24",
"192.88.99.0/24",
"192.168.0.0/16",
"198.18.0.0/15",
"198.51.100.0/24",
"203.0.113.0/24",
"240.0.0.0/4",
"255.255.255.255/32",
"224.0.0.0/4",
]
for network in networks:
try:
ipaddr = struct.unpack(">I", socket.inet_aton(ip))[0]
netaddr, bits = network.split("/")
network_low = struct.unpack(">I", socket.inet_aton(netaddr))[0]
network_high = network_low | 1 << (32 - int(bits)) - 1
if ipaddr <= network_high and ipaddr >= network_low:
return True
except Exception,err:
continue
return False
Since Python 3.3 there is an ipaddress module in the stdlib that you can use.
>>> import ipaddress
>>> ipaddress.ip_address('192.168.0.1').is_private
True
If using Python 2.6 or higher I would strongly recommend to use a backport of this module.
A few days after asking this question, I found out about this Google project, ipaddr-py, which appears to have some of the same functionality with respect to determining if an address is private (is_rfc1918
). Apparently this will be standard in Python 3.1.