在Python中,确定IP地址(例如'127.0.0.1'
或'10.98.76.6'
)是否在专用网络上的最佳方法是什么?代码听起来不难写.但是可能会有更多的边缘情况而不是立即显而易见的,并且需要考虑IPv6支持等.是否有现有的库可以做到这一点?
从Python 3.3开始,stdlib中就有一个ipaddress模块可以使用.
>>> import ipaddress >>> ipaddress.ip_address('192.168.0.1').is_private True
如果使用Python 2.6或更高版本,我强烈建议使用此模块的backport.
查看IPy模块.如果有一个iptype()
似乎做你想要的功能:
>>> from IPy import IP >>> ip = IP('127.0.0.0/30') >>> ip.iptype() 'PRIVATE'
您可以使用http://tools.ietf.org/html/rfc1918和http://tools.ietf.org/html/rfc3330自行检查
.如果您有127.0.0.1,您只需要&
使用掩码(比如说255.0.0.0
),并查看该值是否与任何专用网络的网络地址匹配.所以使用inet_pton你可以做到:127.0.0.1 & 255.0.0.0 = 127.0.0.0
这是代码,说明:
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
另一个实现是计算所有私有块的int值:
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"
这是@Kurt建议的正则表达式方法的固定版本,包括@RobEvans推荐的修复
^ 127.\ d {1,3}.\ d {1,3}.\ d {1,3} $
^ 10.\ d {1,3}.\ d {1,3}.\ d {1,3} $
^ 192.168.\ d {1,3}.\ d {1,3} $
^ 172(1 [6-9] | 2 [0-9] | 3 [0-1]).[0-9] {1,3} [0-9] {1,3} $
def is_ip_private(ip): # https://en.wikipedia.org/wiki/Private_network priv_lo = re.compile("^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$") priv_24 = re.compile("^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$") priv_20 = re.compile("^192\.168\.\d{1,3}.\d{1,3}$") priv_16 = re.compile("^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3}$") res = priv_lo.match(ip) or priv_24.match(ip) or priv_20.match(ip) or priv_16.match(ip) return res is not None