def test_smallest_matching_cidr_v4(): assert smallest_matching_cidr( '192.0.2.0', ['10.0.0.1', '192.0.2.0', '224.0.0.1']) == IPNetwork('192.0.2.0/32') assert smallest_matching_cidr('192.0.2.32', [ '0.0.0.0/0', '10.0.0.0/8', '192.0.0.0/8', '192.0.1.0/24', '192.0.2.0/24', '192.0.3.0/24' ]) == IPNetwork('192.0.2.0/24') assert smallest_matching_cidr('192.0.2.0', ['10.0.0.1', '224.0.0.1']) is None
def _lookup_longest_subnet(self, ip_dst): # debug_info("Going to lookup the longest match subnet", 1) try: f1 = lambda (vni, dic): smallest_matching_cidr(ip_dst, dic["subnet"]) is not None mtchs = {dic["subnet"] : vni for (vni, dic) in filter(f1, self.maps.items()) } # debug_info("mtchs = {0}".format(str(mtchs) ), 1) if not len(mtchs): debug_info("No route was matched.", 2) return None except KeyError as excpt: debug_info("Routing lookup encoutered an error : {0}".format(excpt), 3) return None # debug_info("ip_dst = {0}".format(ip_dst), 1) return mtchs[smallest_matching_cidr(ip_dst, mtchs.keys())]
def filter(self, host): net = netaddr.smallest_matching_cidr(netaddr.IPNetwork(host), list(self.server_networks.keys())) if net is not None: return self.server_networks[net] raise packet.PacketError("Unknown Client: %s" % host)
def check_host(host, allow_localhost=config.ALLOW_CONNECT_LOCALHOST, allow_private=config.ALLOW_CONNECT_PRIVATE): """Check if a given host is a valid DNS name or IPv4 address""" try: ipaddr = socket.gethostbyname(host) except socket.gaierror: raise MistError( "Not a valid IP address or resolvable DNS name: '%s'." % host) if host != ipaddr: msg = "Host '%s' resolves to '%s' which" % (host, ipaddr) else: msg = "Host '%s'" % host if not netaddr.valid_ipv4(ipaddr): raise MistError(msg + " is not a valid IPv4 address.") forbidden_subnets = { '0.0.0.0/8': "used for broadcast messages to the current network", '100.64.0.0/10': ("used for communications between a service provider " "and its subscribers when using a " "Carrier-grade NAT"), '169.254.0.0/16': ("used for link-local addresses between two hosts " "on a single link when no IP address is otherwise " "specified"), '192.0.0.0/24': ("used for the IANA IPv4 Special Purpose Address " "Registry"), '192.0.2.0/24': ("assigned as 'TEST-NET' for use solely in " "documentation and example source code"), '192.88.99.0/24': "used by 6to4 anycast relays", '198.18.0.0/15': ("used for testing of inter-network communications " "between two separate subnets"), '198.51.100.0/24': ("assigned as 'TEST-NET-2' for use solely in " "documentation and example source code"), '203.0.113.0/24': ("assigned as 'TEST-NET-3' for use solely in " "documentation and example source code"), '224.0.0.0/4': "reserved for multicast assignments", '240.0.0.0/4': "reserved for future use", '255.255.255.255/32': ("reserved for the 'limited broadcast' " "destination address"), } if not allow_localhost: forbidden_subnets['127.0.0.0/8'] = ("used for loopback addresses " "to the local host") if not allow_private: for cidr in ('10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'): forbidden_subnets[cidr] = ("used for local communications " "within a private network") cidr = netaddr.smallest_matching_cidr(ipaddr, forbidden_subnets.keys()) if cidr: raise MistError("%s is not allowed. It belongs to '%s' " "which is %s." % (msg, cidr, forbidden_subnets[str(cidr)]))
def _is_in_view(self, record): result = False try: result = bool(netaddr.smallest_matching_cidr(self.remote_ip, record.get('rule').split())) except (AttributeError, netaddr.AddrFormatError, ValueError) as e: logging.error('{}: record id {} view rule invalid: {}: {}'.format( type(self).__name__, record['id'], type(e).__name__, e)) return result
def check_host(host, allow_localhost=config.ALLOW_CONNECT_LOCALHOST, allow_private=config.ALLOW_CONNECT_PRIVATE): """Check if a given host is a valid DNS name or IPv4 address""" try: ipaddr = socket.gethostbyname(host) except UnicodeEncodeError: raise MistError('Please provide a valid DNS name') except socket.gaierror: raise MistError("Not a valid IP address or resolvable DNS name: '%s'." % host) if host != ipaddr: msg = "Host '%s' resolves to '%s' which" % (host, ipaddr) else: msg = "Host '%s'" % host if not netaddr.valid_ipv4(ipaddr): raise MistError(msg + " is not a valid IPv4 address.") forbidden_subnets = { '0.0.0.0/8': "used for broadcast messages to the current network", '100.64.0.0/10': ("used for communications between a service provider " "and its subscribers when using a " "Carrier-grade NAT"), '169.254.0.0/16': ("used for link-local addresses between two hosts " "on a single link when no IP address is otherwise " "specified"), '192.0.0.0/24': ("used for the IANA IPv4 Special Purpose Address " "Registry"), '192.0.2.0/24': ("assigned as 'TEST-NET' for use solely in " "documentation and example source code"), '192.88.99.0/24': "used by 6to4 anycast relays", '198.18.0.0/15': ("used for testing of inter-network communications " "between two separate subnets"), '198.51.100.0/24': ("assigned as 'TEST-NET-2' for use solely in " "documentation and example source code"), '203.0.113.0/24': ("assigned as 'TEST-NET-3' for use solely in " "documentation and example source code"), '224.0.0.0/4': "reserved for multicast assignments", '240.0.0.0/4': "reserved for future use", '255.255.255.255/32': ("reserved for the 'limited broadcast' " "destination address"), } if not allow_localhost: forbidden_subnets['127.0.0.0/8'] = ("used for loopback addresses " "to the local host") if not allow_private: for cidr in ('10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'): forbidden_subnets[cidr] = ("used for local communications " "within a private network") cidr = netaddr.smallest_matching_cidr(ipaddr, forbidden_subnets.keys()) if cidr: raise MistError("%s is not allowed. It belongs to '%s' " "which is %s." % (msg, cidr, forbidden_subnets[str(cidr)]))
def _lookup_longest_subnet(self, ip_dst): # debug_info("Going to lookup the longest match subnet", 1) try: f1 = lambda (vni, dic): smallest_matching_cidr( ip_dst, dic["subnet"]) is not None mtchs = { dic["subnet"]: vni for (vni, dic) in filter(f1, self.maps.items()) } # debug_info("mtchs = {0}".format(str(mtchs) ), 1) if not len(mtchs): debug_info("No route was matched.", 2) return None except KeyError as excpt: debug_info( "Routing lookup encoutered an error : {0}".format(excpt), 3) return None # debug_info("ip_dst = {0}".format(ip_dst), 1) return mtchs[smallest_matching_cidr(ip_dst, mtchs.keys())]
def _is_in_view(self, record): result = False try: result = bool( netaddr.smallest_matching_cidr(self.remote_ip, record.get('rule').split())) except (AttributeError, netaddr.AddrFormatError, ValueError) as e: logging.error('{}: record id {} view rule invalid: {}: {}'.format( type(self).__name__, record['id'], type(e).__name__, e)) return result
def checkCIDR(self, srcIP): if self.CIDRList is None: return True if srcIP is None: return False try: srcIP = netaddr.IPAddress(srcIP) except: return False try: cidrs = [netaddr.IPNetwork(item.rstrip().lstrip()) for item in self.CIDRList.split(",")] return netaddr.smallest_matching_cidr(srcIP, cidrs) is not None except: return True
def parse_config(filepath): mac_base_int = int( get_if_hwaddr(linux.get_if_list()[0]).replace(":", ""), 16) # mac_base_int = [int(sec, 16) for sec in get_if_hwaddr().split(":")] attrs_valid = set(["vni", "subnet", "gw_ip", "vteps"]) # attrs_valid = set(["vlan", "vni", "subnet", "gw_ip"]) try: with open(filepath) as f: maps = json.load(f) for m in maps: assert set(m.keys( )) == attrs_valid, "Invalid json key/value was discovered." m["subnet"] = IPNetwork(m["subnet"]) m["gw_ip"] = IPAddress(m["gw_ip"]) is_inc = smallest_matching_cidr(m["gw_ip"], m["subnet"]) assert is_inc is not None, "The subnet and gw_ip mismatch." assert all( [is_valid_ipv4(vtep[0]) for vtep in m["vteps"].items() ] ), \ "There are some invalid representations of IPv4 address." assert is_valid_vni( m["vni"] ), "Out of the valid VNI range. (0 < VNI < 2 ** 24)" mac_int = (mac_base_int + m["vni"]) % MAC_MODULER mac_hex = "{0:012x}".format(mac_int) m["hwaddr"] = ":".join([ mac_hex[idx:idx + 2] for idx in xrange(len(mac_hex)) if idx % 2 == 0 ]) # mac_int[-1] = (mac_int[-1] + m["vni"]) % 256 # m["hwaddr"] = ":".join( ["%02x" % sec for sec in mac_int] ) maps = {m["vni"]: m for m in maps} return maps except AssertionError as excpt: print excpt print("Program exits.") sys.exit(1) except Exception as excpt: print excpt sys.exit(1)
def checkCIDR(self, srcIP): if self.CIDRList is None: return True if srcIP is None: return False try: srcIP = netaddr.IPAddress(srcIP) except: return False try: cidrs = [ netaddr.IPNetwork(item.rstrip().lstrip()) for item in self.CIDRList.split(",") ] return netaddr.smallest_matching_cidr(srcIP, cidrs) is not None except: return True
def test_cidr_matching_v4(): networks = [str(c) for c in IPNetwork('192.0.2.128/27').supernet(22)] assert networks == [ '192.0.0.0/22', '192.0.2.0/23', '192.0.2.0/24', '192.0.2.128/25', '192.0.2.128/26', ] assert all_matching_cidrs('192.0.2.0', networks) == [ IPNetwork('192.0.0.0/22'), IPNetwork('192.0.2.0/23'), IPNetwork('192.0.2.0/24'), ] assert smallest_matching_cidr('192.0.2.0', networks) == IPNetwork('192.0.2.0/24') assert largest_matching_cidr('192.0.2.0', networks) == IPNetwork('192.0.0.0/22')
def parse_config(filepath): mac_base_int = int(get_if_hwaddr(linux.get_if_list()[0]).replace(":", ""), 16) # mac_base_int = [int(sec, 16) for sec in get_if_hwaddr().split(":")] attrs_valid = set(["vni", "subnet", "gw_ip", "vteps"]) # attrs_valid = set(["vlan", "vni", "subnet", "gw_ip"]) try: with open(filepath) as f: maps = json.load(f) for m in maps: assert set(m.keys() ) == attrs_valid, "Invalid json key/value was discovered." m["subnet"] = IPNetwork(m["subnet"]) m["gw_ip"] = IPAddress(m["gw_ip"]) is_inc = smallest_matching_cidr(m["gw_ip"], m["subnet"]) assert is_inc is not None, "The subnet and gw_ip mismatch." assert all( [is_valid_ipv4(vtep[0]) for vtep in m["vteps"].items() ] ), \ "There are some invalid representations of IPv4 address." assert is_valid_vni(m["vni"]), "Out of the valid VNI range. (0 < VNI < 2 ** 24)" mac_int = (mac_base_int + m["vni"]) % MAC_MODULER mac_hex = "{0:012x}".format(mac_int) m["hwaddr"] = ":".join( [mac_hex[idx:idx+2] for idx in xrange(len(mac_hex) ) if idx % 2 == 0] ) # mac_int[-1] = (mac_int[-1] + m["vni"]) % 256 # m["hwaddr"] = ":".join( ["%02x" % sec for sec in mac_int] ) maps = { m["vni"] : m for m in maps} return maps except AssertionError as excpt: print excpt print("Program exits.") sys.exit(1) except Exception as excpt: print excpt sys.exit(1)
def UpdateVlans(): # create a vlan dict { netaddr.IPNetwork : Vlan } vlans={} for v in Vlan.objects.all(): try: vlans[netaddr.IPNetwork(v.network + "/" + v.netmask)] = v except netaddr.AddrFormatError: print "WARNING: vlan %s has no valid network/netmask: %s/%s" % (v.vlannumber, v.network,v.netmask) # check for each host if ip is in a vlan for h in Host.objects.all(): #print "DEBUG: processing %s, %s" % (h,datetime.now().ctime()) try: ip=netaddr.IPAddress(h.ip) except netaddr.AddrFormatError: print "WARNING: %s as no good ip: %s" % (h,h.ip) pass for network,vlan in vlans.iteritems(): if netaddr.smallest_matching_cidr(ip,network): if h.vlan_id != vlan.id: h.vlan=vlan h.save() print "INFO: add %s to vlan %s" % (h,vlan) pass
def secret_for_host(self, host: str) -> str: ipnetwork = netaddr.smallest_matching_cidr( netaddr.IPAddress(host), list(self.secrets.keys()), ) return self.secrets.get(ipnetwork)
def test_smallest_matching_cidr_v4(): assert smallest_matching_cidr('192.0.2.0', ['10.0.0.1', '192.0.2.0', '224.0.0.1']) == IPNetwork('192.0.2.0/32') assert smallest_matching_cidr('192.0.2.32', ['0.0.0.0/0', '10.0.0.0/8', '192.0.0.0/8', '192.0.1.0/24', '192.0.2.0/24', '192.0.3.0/24']) == IPNetwork('192.0.2.0/24') assert smallest_matching_cidr('192.0.2.0', ['10.0.0.1', '224.0.0.1']) is None
def _find_routers_via_routes_for_floatingip(self, context, internal_port, internal_subnet_id, external_network_id): """Find routers with route to the internal IP address. Iterate over the routers that belong to the same tenant as 'internal_port'. For each router check that the router is connected to the external network and whether there is a route to the internal IP address. Consider only routers for which there is a path from the nexthop of the route to the internal port. Sort the list of routers to have the router with the most specific route first (largest CIDR prefix mask length). @param context: neutron api request context @param internal_port: the port dict for the association @param internal_subnet_id: the subnet for the association @param external_network_id: the network of the floatingip @return: a sorted list of matching routers """ original_context = context context = elevate_context(context) internal_ip_address = [ ip['ip_address'] for ip in internal_port['fixed_ips'] if ip['subnet_id'] == internal_subnet_id ][0] # find the tenant routers tenant_id = internal_port['tenant_id'] routers = self.get_routers(context, filters={'tenant_id': [tenant_id]}) prefix_routers = [] for router in routers: # verify that the router is on "external_network" gw_info = router.get(EXTERNAL_GW_INFO) if not gw_info or gw_info['network_id'] != external_network_id: continue # find a matching route if 'routes' not in router: continue cidr_nexthops = {} for route in router['routes']: cidr = netaddr.IPNetwork(route['destination']) if cidr not in cidr_nexthops: cidr_nexthops[cidr] = [] cidr_nexthops[cidr].append(route['nexthop']) smallest_cidr = netaddr.smallest_matching_cidr(internal_ip_address, cidr_nexthops.keys()) if not smallest_cidr: continue # validate that there exists a path to "internal_port" for nexthop in cidr_nexthops[smallest_cidr]: net_id = self._find_net_for_nexthop(context, context.tenant_id, router['id'], nexthop) if net_id and self._is_net_reachable_from_net( context, context.tenant_id, net_id, internal_port['network_id']): prefix_routers.append((smallest_cidr.prefixlen, router['id'])) break context = original_context return [p_r[1] for p_r in sorted(prefix_routers, reverse=True)]
def _find_routers_via_routes_for_floatingip(self, context, internal_port, internal_subnet_id, external_network_id): """Find routers with route to the internal IP address. Iterate over the routers that belong to the same tenant as 'internal_port'. For each router check that the router is connected to the external network and whether there is a route to the internal IP address. Consider only routers for which there is a path from the nexthop of the route to the internal port. Sort the list of routers to have the router with the most specific route first (largest CIDR prefix mask length). @param context: neutron api request context @param internal_port: the port dict for the association @param internal_subnet_id: the subnet for the association @param external_network_id: the network of the floatingip @return: a sorted list of matching routers """ original_context = context context = elevate_context(context) internal_ip_address = [ ip['ip_address'] for ip in internal_port['fixed_ips'] if ip['subnet_id'] == internal_subnet_id ][0] # find the tenant routers tenant_id = internal_port['tenant_id'] routers = self.get_routers(context, filters={'tenant_id': [tenant_id]}) prefix_routers = [] for router in routers: # verify that the router is on "external_network" gw_info = router.get(EXTERNAL_GW_INFO) if not gw_info or gw_info['network_id'] != external_network_id: continue # find a matching route if 'routes' not in router: continue cidr_nexthops = {} for route in router['routes']: cidr = netaddr.IPNetwork(route['destination']) if cidr not in cidr_nexthops: cidr_nexthops[cidr] = [] cidr_nexthops[cidr].append(route['nexthop']) smallest_cidr = netaddr.smallest_matching_cidr( internal_ip_address, cidr_nexthops.keys()) if not smallest_cidr: continue # validate that there exists a path to "internal_port" for nexthop in cidr_nexthops[smallest_cidr]: net_id = self._find_net_for_nexthop(context, context.tenant_id, router['id'], nexthop) if net_id and self._is_net_reachable_from_net( context, context.tenant_id, net_id, internal_port['network_id']): prefix_routers.append( (smallest_cidr.prefixlen, router['id'])) break context = original_context return [p_r[1] for p_r in sorted(prefix_routers, reverse=True)]