def get_ips_list(ranges): """Get the IP addresses list from a list of ranges. :param list ranges: List of ranges. :returns: List of IP addresses. :rtype: list of cidr ips (https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) """ ip_set = IPSet() for ip_range in ranges: try: # It's a glob if '*' in ip_range or '-' in ip_range: ip_set.add(IPGlob(ip_range)) # It's a network elif '/' in ip_range: ip_set.add(IPNetwork(ip_range)) # Simple IP else: ip_set.add(IPAddress(ip_range)) except Exception: pass return [str(ip.cidr) for ip in ip_set.iter_cidrs()]
def is_ip_in_list(ip_address, addresses_list): """Check if address IP is in list. :param ip_address: Address IP to check :param addresses_list: Range of IP, network or simple IP. :returns: True if given IP is in list. """ if not isinstance(addresses_list, list): raise Exception('Given parameter is not a list.') ip_set = IPSet() for ip_range in addresses_list: try: # It's a glob if '*' in ip_range or '-' in ip_range: ip_set.add(IPGlob(ip_range)) # It's a network elif '/' in ip_range: ip_set.add(IPNetwork(ip_range)) # Simple IP else: ip_set.add(IPAddress(ip_range)) except Exception: pass try: return ip_address in ip_set except Exception: return False
def _get_ips_from_glob(glob_ips): ip_glob = IPGlob(glob_ips) ips = set() for ip in ip_glob: ips.add(str(ip)) return ips
def ipglob(self, *args): """Returns a random address from within the given ip global https://pythonhosted.org/netaddr/api.html#ip-glob-ranges IPGLOB:GLOB %{IPGLOB:*.*.*.*} -> '' """ call_args = list(args) return self.random.choice(IPGlob(call_args.pop(0)))
def proxy_list(human_readable): globs = [] addrs = [] for item in human_readable: if '*' in item or '-' in item: globs.append(IPGlob(item)) else: addrs.append(item) return IPSet(chain(chain.from_iterable(globs), addrs))
def test_make_ip_set(self): def is_in(ipaddr, ipset): ipset = make_ip_set(ipset) return IPAddress(ipaddr) in ipset # Test individual IPs self.assertTrue(is_in("127.0.0.1", "127.0.0.1")) self.assertFalse(is_in("127.0.0.2", "127.0.0.1")) # Test globbing self.assertTrue(is_in("127.0.0.1", "127.0.0.*")) self.assertTrue(is_in("127.0.1.2", "127.0.*.*")) self.assertTrue(is_in("127.0.0.1", "127.0.0.*")) self.assertFalse(is_in("127.0.1.2", "127.0.0.*")) self.assertTrue(is_in("127.0.0.1", "127.0.0.1-5")) self.assertTrue(is_in("127.0.0.5", "127.0.0.1-5")) self.assertFalse(is_in("127.0.0.6", "127.0.0.1-5")) # Test networks self.assertTrue(is_in("127.0.0.1", "127.0.0.0/8")) self.assertTrue(is_in("127.0.0.1", "127.0.0.0/16")) self.assertTrue(is_in("127.0.0.1", "127.0.0.0/24")) self.assertFalse(is_in("127.0.1.2", "127.0.0.0/24")) # Test literal None self.assertFalse(is_in("127.0.0.1", None)) # Test special strings self.assertTrue(is_in("127.0.0.1", "local")) self.assertTrue(is_in("127.0.0.1", "all")) GOOGLE_DOT_COM = "74.125.237.20" self.assertFalse(is_in(GOOGLE_DOT_COM, "local")) self.assertTrue(is_in(GOOGLE_DOT_COM, "all")) # Test with a list of stuff ips = ["127.0.0.1", "127.0.1.*"] self.assertTrue(is_in("127.0.0.1", ips)) self.assertTrue(is_in("127.0.1.1", ips)) self.assertFalse(is_in("127.0.0.2", ips)) self.assertTrue(is_in("127.0.1.2", ips)) # Test with a string-list of stuff ips = "123.123.0.0/16 local" self.assertTrue(is_in("127.0.0.1", ips)) self.assertTrue(is_in("127.0.1.1", ips)) self.assertTrue(is_in("123.123.1.1", ips)) self.assertFalse(is_in("124.0.0.1", ips)) # Test with list-splitting edge-cases self.assertTrue(is_in("127.0.0.1", "127.0.0.2,127.0.0.1")) self.assertTrue(is_in("127.0.0.1", "127.0.0.2, 127.0.0.1")) self.assertTrue(is_in("127.0.0.1", "127.0.0.2 127.0.0.1")) # Test with various strange inputs to the parser self.assertTrue(is_in("127.0.0.1", IPAddress("127.0.0.1"))) self.assertTrue(is_in("127.0.0.1", int(IPAddress("127.0.0.1")))) self.assertTrue(is_in("127.0.0.1", IPNetwork("127.0.0.1/8"))) self.assertTrue(is_in("127.0.0.1", IPGlob("127.0.0.*"))) self.assertTrue(is_in("127.0.0.1", IPRange("127.0.0.1", "127.0.0.2"))) self.assertTrue(is_in("127.0.0.1", IPSet(["127.0.0.1/8"]))) self.assertFalse(is_in("127.0.0.1", "")) self.assertFalse(is_in("127.0.0.1", None)) self.assertRaises(ValueError, is_in, "127.0.0.1", 3.14159) self.assertRaises(ValueError, is_in, "127.0.0.1", Ellipsis)
def with_proxy_set(cls, ranges): from netaddr import IPSet, IPGlob from itertools import chain globs = [] addrs = [] for item in ranges: if '*' in item or '-' in item: globs.append(IPGlob(item)) else: addrs.append(item) ipset = IPSet(chain(chain.from_iterable(globs), addrs)) return type(cls.__name__, (cls, ), {'_REAL_IP_SET': ipset})
def ipglob(glob): """ Returns an IPGlob object from the netaddr library. >>> glob = ipglob("192.168.32.*") >>> type(glob) <class 'netaddr.ip.glob.IPGlob'> >>> glob.is_private() True """ from netaddr import IPGlob return IPGlob(glob)
def ipstr2range(ip_str, format='range'): init = IPRange if format == 'range' else IPSet if ip_str == '*': ip_str = '0.0.0.0/0' if '*' in ip_str: ipglob = IPGlob(ip_str) iprange = IPRange(ipglob[0], ipglob[-1]) return iprange if format == 'range' else init(iprange) if '-' in ip_str: start, end = ip_str.split('-') iprange = IPRange(start, end) # start[:start.rindex('.') + 1] + return iprange if format == 'range' else init(iprange) else: if format == 'range': network = IPNetwork(ip_str) return init(network[0], network[-1]) return init([ip_str])
def parse_ip_set(ipaddrs): """Parse a string specification into an IPSet. This function takes a string representing a set of IP addresses and parses it into an IPSet object. Acceptable formats for the string include: * "all": all possible IPv4 and IPv6 addresses * "local": all local addresses of the machine * "A.B.C.D" a single IP address * "A.B.C.D/N" a network address specification * "A.B.C.*" a glob matching against all possible numbers * "A.B.C.D-E" a glob matching against a range of numbers * a whitespace- or comma-separated string of the above """ ipset = IPSet() ipaddrs = ipaddrs.lower().strip() if not ipaddrs: return ipset for ipspec in _COMMA_OR_WHITESPACE.split(ipaddrs): # The string "local" maps to all local addresses on the machine. if ipspec == "local": ipset.add(IPNetwork("127.0.0.0/8")) for addr in get_local_ip_addresses(): ipset.add(addr) # The string "all" maps to app IPv4 and IPv6 addresses. elif ipspec == "all": ipset.add(IPNetwork("0.0.0.0/0")) ipset.add(IPNetwork("::")) # Strings containing a "/" are assumed to be network specs elif "/" in ipspec: ipset.add(IPNetwork(ipspec)) # Strings containing a "*" or "-" are assumed to be glob patterns elif "*" in ipspec or "-" in ipspec: for cidr in IPGlob(ipspec).cidrs(): ipset.add(cidr) # Anything else must be a single address else: ipset.add(IPAddress(ipspec)) return ipset
def __init__(self, ip_list=[], hostname_list=[], netblock_list=[], netrange_list=[], auto_coalesce_ip=True, auto_resolve_hostnames=False): self._auto_coalesce = auto_coalesce_ip self._auto_resolve_hostnames = auto_resolve_hostnames not_ip = [x for x in ip_list if not Scope.is_ip(x)] if not_ip: raise ValueError('Value(s) ' + str(not_ip) + ' are provided as IP but cannot be casted as such') self._ip_list = IPSet(ip_list) not_hostname = [x for x in hostname_list if not Scope.is_hostname(x)] if not_hostname: raise ValueError('Value(s) ' + str(not_hostname) + ' are provided as hostnames but cannot be casted as such') self._hostname_list = set(hostname_list) not_netblock = [x for x in netblock_list if not Scope.is_netblock(x)] if not_netblock: raise ValueError('Value(s) ' + str(not_netblock) + ' are provided as netblocks but cannot be casted as such') self._netblock_list = set(IPNetwork(x) for x in set(netblock_list)) not_netrange = [x for x in netrange_list if not Scope.is_netrange(x)] if not_netrange: raise ValueError('Value(s) ' + str(not_netrange) + ' are provided as netranges but cannot be casted as such') self._netrange_list = set() for netrange in set(netrange_list): if self._netrange_ip_to_int(netrange): self._netrange_list.add(IPGlob(netrange)) else: (ip1, ip2) = (x.strip() for x in netrange.split('-')) self._netrange_list.add(IPRange(ip1, ip2)) if self._auto_resolve_hostnames: self._resolve_hostnames() if self._auto_coalesce: self._coalesce_ip_list()
def cidrize(ipstr, strict=False, modular=True): """ This function tries to determine the best way to parse IP addresses correctly & has all the logic for trying to do the right thing! Returns a list of consolidated netaddr objects. Input can be several formats:: '192.0.2.18' '192.0.2.64/26' '192.0.2.80-192.0.2.85' '192.0.2.170-175' '192.0.2.8[0-5]' '192.0.2.[0-29]' '192.168.4.6[1234]' '1.2.3.*' '192.0.2.170-175, 192.0.2.80-192.0.2.85, 192.0.2.64/26' Hyphenated ranges do not need to form a CIDR block. Netaddr does most of the heavy lifting for us here. Input can NOT be:: 192.0.2.0 0.0.0.255 (hostmask) 192.0.2.0 255.255.255.0 (netmask) Does NOT accept network or host mask notation at this time! Defaults: * parsing exceptions will raise a CidrizeError (modular=True). * results will be returned as a spanning CIDR (strict=False). :param ipstr: IP string to be parsed. :param modular: Set to False to cause exceptions to be stripped & the error text will be returned as a list. This is intended for use with scripts or APIs out-of-the box. Example: >>> import cidrize as c >>> c.cidrize('1.2.3.4-1.2.3.1099') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/j/jathan/sandbox/cidrize.py", line 153, in cidrize raise CidrizeError(err) cidrize.CidrizeError: base address '1.2.3.1099' is not IPv4 >>> c.cidrize('1.2.3.4-1.2.3.1099', modular=False) ["base address '1.2.3.1099' is not IPv4"] :param strict: Set to True to return explicit networks based on start/end addresses. Example: >>> import cidrize as c >>> c.cidrize('1.2.3.4-1.2.3.10') [IPNetwork('1.2.3.0/28')] >>> c.cidrize('1.2.3.4-1.2.3.10', strict=True) [IPNetwork('1.2.3.4/30'), IPNetwork('1.2.3.8/31'), IPNetwork('1.2.3.10/32')] """ ip = None # Short-circuit to parse commas since it calls back here anyway if ',' in ipstr: return parse_commas(ipstr, strict=strict, modular=modular) # Short-circuit for hostnames (we're assuming first char is alpha) if hostname_re.match(ipstr): raise CidrizeError('Cannot parse hostnames!') # Otherwise try everything else result = None try: # Parse "everything" & immediately return; strict/loose doesn't apply if ipstr in EVERYTHING: log.debug("Trying everything style...") return [IPNetwork('0.0.0.0/0')] # Parse old-fashioned CIDR notation & immediately return; strict/loose doesn't apply # Now with IPv6! elif cidr_re.match(ipstr) or is_ipv6(ipstr): log.debug("Trying CIDR style...") ip = IPNetwork(ipstr) return [ip.cidr] # Parse 1.2.3.118-1.2.3.121 range style elif range_re.match(ipstr): log.debug("Trying range style...") result = parse_range(ipstr) # Parse 1.2.3.4-70 hyphen style elif hyphen_re.match(ipstr): log.debug("Trying hyphen style...") result = parse_hyphen(ipstr) # Parse 1.2.3.* glob style elif glob_re.match(ipstr): log.debug("Trying glob style...") ipglob = IPGlob(ipstr) result = spanning_cidr(ipglob) # Parse 1.2.3.4[5-9] or 1.2.3.[49] bracket style as a last resort elif bracket_re.match(ipstr): log.debug("Trying bracket style...") result = parse_brackets(ipstr) # If result still isn't set, let's see if it's IPv6?? elif result is None: log.debug("Trying bare IPv6 parse...") result = IPNetwork(ipstr) # This will probably fail 100% of the time. By design. else: raise CidrizeError("Could not determine parse style for '%s'" % ipstr) # If it's a single host, just return it wrapped in a list if result.size == 1: log.debug("Returning a single host!") return [result.cidr] # Logic to honor strict/loose, except IPRange. Doing a spanning_cidr on # an IPRange can be super slow if the range is large (such as a /8), so # IPRange objects larger than MAX_RANGE_LEN will always be strict. if not strict: if isinstance(result, IPRange) and result.size >= MAX_RANGE_LEN: log.debug( 'IPRange objects larger than /18 will always be strict.') return result.cidrs() return [spanning_cidr(result)] else: try: return result.cidrs() # IPGlob and IPRange have .cidrs() except AttributeError as err: return result.cidr # IPNetwork has .cidr except (AddrFormatError, TypeError, ValueError) as err: if modular: raise CidrizeError(err) return [str(err)]
def test_ipglob_boolean_evaluation(): assert bool(IPGlob('*.*.*.*')) assert bool(IPGlob('0.0.0.0'))
def test_ipglob_basic(): #TODO: do the same testing on IPGlob as IPRange. assert IPGlob('192.0.2.*') == IPNetwork('192.0.2.0/24')