Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
    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())]
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
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)]))
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
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)]))
Ejemplo n.º 7
0
    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())]
Ejemplo n.º 8
0
    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
Ejemplo n.º 9
0
 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
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
 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
Ejemplo n.º 12
0
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')
Ejemplo n.º 13
0
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')
Ejemplo n.º 14
0
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)
Ejemplo n.º 15
0
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
Ejemplo n.º 16
0
 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)
Ejemplo n.º 17
0
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
Ejemplo n.º 18
0
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)]