How can I check if an ip is in a network in python

2019-01-03 08:37发布

Given an ip address (say 192.168.0.1), how do I check if it's in a network (say 192.168.0.0/24) in Python?

Are there general tools in Python for ip address manipulation? Stuff like host lookups, ip adddress to int, network address with netmask to int and so on? Hopefully in the standard Python library for 2.5.

25条回答
时光不老,我们不散
2楼-- · 2019-01-03 09:05

Relying on the "struct" module can cause problems with endian-ness and type sizes, and just isn't needed. Nor is socket.inet_aton(). Python works very well with dotted-quad IP addresses:

def ip_to_u32(ip):
  return int(''.join('%02x' % int(d) for d in ip.split('.')), 16)

I need to do IP matching on each socket accept() call, against a whole set of allowable source networks, so I precompute masks and networks, as integers:

SNS_SOURCES = [
  # US-EAST-1
  '207.171.167.101',
  '207.171.167.25',
  '207.171.167.26',
  '207.171.172.6',
  '54.239.98.0/24',
  '54.240.217.16/29',
  '54.240.217.8/29',
  '54.240.217.64/28',
  '54.240.217.80/29',
  '72.21.196.64/29',
  '72.21.198.64/29',
  '72.21.198.72',
  '72.21.217.0/24',
  ]

def build_masks():
  masks = [ ]
  for cidr in SNS_SOURCES:
    if '/' in cidr:
      netstr, bits = cidr.split('/')
      mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
      net = ip_to_u32(netstr) & mask
    else:
      mask = 0xffffffff
      net = ip_to_u32(cidr)
    masks.append((mask, net))
  return masks

Then I can quickly see if a given IP is within one of those networks:

ip = ip_to_u32(ipstr)
for mask, net in cached_masks:
  if ip & mask == net:
    # matched!
    break
else:
  raise BadClientIP(ipstr)

No module imports needed, and the code is very fast at matching.

查看更多
登录 后发表回答