#!/usr/bin/env python3.8 import os from pathlib import Path from ipaddress import IPv4Network from urllib.request import urlretrieve import pytest from ips import (ServiceIPRange, parse_ipv4_service_ranges, get_aws_service_range) URL = "https://bites-data.s3.us-east-2.amazonaws.com/ip-ranges.json" TMP = os.getenv("TMP", "/tmp") PATH = Path(TMP, "ip-ranges.json") IP = IPv4Network('192.0.2.8/29') @pytest.fixture(scope='module') def json_file(): """Import data into tmp folder""" urlretrieve(URL, PATH) return PATH # write your pytest code ... def test_dataclass(): sipr = ServiceIPRange("TestService", "TestRegion", IP) assert str( sipr ) == f"{IP} is allocated to the TestService service in the TestRegion region"
for vlan_interface in vlan_interfaces: # determine current ip address ipv4_addr = vlan_interface.re_match_iter_typed(r"ip\saddress\s(\S+\s+\S+)", result_type=IPv4Obj) # determine the current interface name and VLAN ID vlan_interface_string = vlan_interface.text.lstrip("interface ") vlan_id = vlan_interface_string.lstrip("Vlan") # the current SVI address is used as a HSRP virtual IP virtual_ip = ipv4_addr.ip_object # at this point we need to determine the next addresses which are used for the primary and secondary switch # we will try, if the next two addresses are part of the network, otherwise we will use the previous two # addresses ipv4_network = IPv4Network(ipv4_addr.network) if (ipv4_addr.ip_object + 1) in ipv4_network.hosts(): primary_ip = ipv4_addr.ip_object + 1 secondary_ip = ipv4_addr.ip_object + 2 else: primary_ip = ipv4_addr.ip_object - 1 secondary_ip = ipv4_addr.ip_object - 2 # check for secondary IPv4 addresses add_ip_addresses = [] secondary_ipv4_address_lines = vlan_interface.re_search_children(r"^ ip address .* secondary$") for sec_ipv4_cmd in secondary_ipv4_address_lines: # another way to convert the ip address command sec_ipv4_addr = sec_ipv4_cmd.text[len(" ip address "):] sec_ipv4_addr = sec_ipv4_addr.rstrip(" secondary") sec_ipv4_addr = sec_ipv4_addr.replace(" ", "/")
def l2_assignment_strategy(self): self.add_switches() ip_generator = IPv4Network(str("10.0.0.0/16")).hosts() #add links and configure them: ips, macs, etc #assumes hosts are connected to one switch only #reserve ips for normal hosts for host_name in self._hosts: if self.check_host_valid_ip_from_name(host_name): host_num = int(host_name[1:]) upper_byte = (host_num & 0xff00) >> 8 lower_byte = (host_num & 0x00ff) host_ip = "10.0.%d.%d" % (upper_byte, lower_byte) self.reserved_ips[host_name] = host_ip for link in self._links: if self.is_host_link(link): host_name = link[self.get_host_position(link)] direct_sw = link[self.get_sw_position(link)] if self.check_host_valid_ip_from_name(host_name): host_ip = self.reserved_ips[host_name] #we check if for some reason the ip was already given by the ip_generator. This #can only happen if the host naming is not <h_x> #this should not be possible anymore since we reserve ips for h_x hosts while host_ip in self.already_assigned_ips: host_ip = str(next(ip_generator).compressed) self.already_assigned_ips.add(host_ip) else: host_ip = next(ip_generator).compressed #we check if for some reason the ip was already given by the ip_generator. This #can only happen if the host naming is not <h_x> while host_ip in self.already_assigned_ips or host_ip in list( self.reserved_ips.values()): host_ip = str(next(ip_generator).compressed) self.already_assigned_ips.add(host_ip) host_mac = ip_address_to_mac(host_ip) % (0) direct_sw_mac = ip_address_to_mac(host_ip) % (1) ops = self._hosts[host_name] ops.pop("ip", None) ops.pop("mac", None) self.addHost(host_name, ip=host_ip + "/16", mac=host_mac, **ops) self.addLink(host_name, direct_sw, delay=link['delay'], bw=link['bw'], loss=link['loss'], addr1=host_mac, addr2=direct_sw_mac, weight=link["weight"], max_queue_size=link["queue_length"]) self.addSwitchPort(direct_sw, host_name) self.hosts_info[host_name] = { "sw": direct_sw, "ip": host_ip, "mac": host_mac, "mask": 24 } #switch to switch link else: self.addLink(link['node1'], link['node2'], delay=link['delay'], bw=link['bw'], loss=link['loss'], weight=link["weight"], max_queue_size=link["queue_length"]) self.addSwitchPort(link['node1'], link['node2']) self.addSwitchPort(link['node2'], link['node1']) self.add_cpu_port() self.printPortMapping()
def mixed_assignment_strategy(self): sw_to_id = self.add_switches() sw_to_generator = {} #change the id to a generator for that subnet for sw, sw_id in list(sw_to_id.items()): upper_bytex = (sw_id & 0xff00) >> 8 lower_bytex = (sw_id & 0x00ff) net = "10.%d.%d.0/24" % (upper_bytex, lower_bytex) sw_to_generator[sw] = IPv4Network(str(net)).hosts() #reserve ips for link in self._links: if self.is_host_link(link): host_name = link[self.get_host_position(link)] direct_sw = link[self.get_sw_position(link)] sw_id = sw_to_id[direct_sw] upper_byte = (sw_id & 0xff00) >> 8 lower_byte = (sw_id & 0x00ff) if self.check_host_valid_ip_from_name(host_name): host_num = int(host_name[1:]) assert host_num < 254 host_ip = "10.%d.%d.%d" % (upper_byte, lower_byte, host_num) self.reserved_ips[host_name] = host_ip #add links and configure them: ips, macs, etc #assumes hosts are connected to one switch only for link in self._links: if self.is_host_link(link): host_name = link[self.get_host_position(link)] direct_sw = link[self.get_sw_position(link)] sw_id = sw_to_id[direct_sw] upper_byte = (sw_id & 0xff00) >> 8 lower_byte = (sw_id & 0x00ff) ip_generator = sw_to_generator[direct_sw] if self.check_host_valid_ip_from_name(host_name): host_ip = self.reserved_ips[host_name] #we check if for some reason the ip was already given by the ip_generator. This #can only happen if the host naming is not <h_x> while host_ip in self.already_assigned_ips: host_ip = str(next(ip_generator).compressed) self.already_assigned_ips.add(host_ip) else: host_ip = next(ip_generator).compressed #we check if for some reason the ip was already given by the ip_generator. This #can only happen if the host naming is not <h_x> while host_ip in self.already_assigned_ips or host_ip in list( self.reserved_ips.values()): host_ip = str(next(ip_generator).compressed) self.already_assigned_ips.add(host_ip) host_gw = "10.%d.%d.254" % (upper_byte, lower_byte) host_mac = ip_address_to_mac(host_ip) % (0) direct_sw_mac = ip_address_to_mac(host_ip) % (1) ops = self._hosts[host_name] ops.pop("ip", None) ops.pop("mac", None) self.addHost(host_name, ip=host_ip + "/24", mac=host_mac, defaultRoute='via %s' % host_gw, **ops) self.addLink(host_name, direct_sw, delay=link['delay'], bw=link['bw'], loss=link['loss'], addr1=host_mac, addr2=direct_sw_mac, weight=link["weight"], max_queue_size=link["queue_length"]) self.addSwitchPort(direct_sw, host_name) self.hosts_info[host_name] = { "sw": direct_sw, "ip": host_ip, "mac": host_mac, "mask": 24 } #switch to switch link else: self.addLink(link['node1'], link['node2'], delay=link['delay'], bw=link['bw'], loss=link['loss'], weight=link["weight"], max_queue_size=link["queue_length"]) self.addSwitchPort(link['node1'], link['node2']) self.addSwitchPort(link['node2'], link['node1']) self.add_cpu_port() self.printPortMapping()
def ipv4_slash_zero(self) -> bool: """Returns True if `CidrIp` matches `0.0.0.0/0`, otherwise False.""" # Remove after this is fixed https://bugs.python.org/issue38655 if not self.CidrIp: return False return self.CidrIp == IPv4Network(IPV4_ZERO_VALUE)
tcpr = sr1(tcps[pkt], timeout=t, verbose=v) # Send packet and capture response if tcpr is None: # No response print "Port", stport, "is filtered" elif (tcpr[TCP].flags == 0x12): # SYN-ACK print "Port", stport, "is open" elif (tcpr[TCP].flags == 0x14): # RST print "Port", stport, "is closed" stport += 1 # If an IP range is specified, identify input as such and make list of addresses using ipv4network for i in range(0, len(sip)): if (sip[i] == "/"): sips = IPv4Network(sip) for host in sips: # Feed each of these IP's in one by one to spkt so appropriate ports can be probed spkt(host) elif ( sip[i] != "/" ): # Loop through all characters of IP to see if a range is specified i += 1 if (i == len(sip) ): # Single IP addresses will not have '/' characters at any point host = sip spkt( host ) # Therefore, such IPs can be passed straight into our packet creator function else: continue
def __init__(self, wanted_ip: str) -> None: self.name = wanted_ip self.wanted_ip = IPv4Network(wanted_ip)
def main(args): try: config = get_config(args.config, CONFIG_PARAMETERS) email = read_email(args.input) except Exception as ex: write_log(args.log, ex) return ReturnCode.ERROR if "Received" not in email: write_log(args.log, "Header received does not exist") return ReturnCode.ERROR header_received = str(email.get("Received")) if not header_received: write_log(args.log, "Header received is empty") return ReturnCode.ERROR sender_ip = re.search(r"\[([0-9.]+)\]", header_received) if not sender_ip: write_log(args.log, "Cannot find sender IP") return ReturnCode.ERROR sender_ip = sender_ip.group(1) try: ipv4_address = IPv4Address(sender_ip) except Exception: write_log(args.log, "Invalid sender IP") return ReturnCode.ERROR for network in config.internal_networks: try: ipv4_network = IPv4Network(network) except Exception: write_log(args.log, "Invalid CIDR '{}'".format(network)) return ReturnCode.ERROR if ipv4_address in ipv4_network: break else: return ReturnCode.SENDER_EXTERNAL if "From" not in email: write_log(args.log, "Header does not exist") return ReturnCode.ERROR header_from = str(email.get("From")) if not header_from: write_log(args.log, "Header from is empty") return ReturnCode.ERROR sender_address = extract_email_address(header_from) if not sender_address: write_log(args.log, "Cannot find sender address") return ReturnCode.ERROR sender_address = sender_address.group(1) index_at = sender_address.find("@") if index_at == -1: write_log(args.log, "Invalid sender address") return ReturnCode.ERROR sender_domain = sender_address[index_at + 1:] if not sender_domain: write_log(args.log, "Empty sender domain") return ReturnCode.ERROR try: set_address = get_address_list(config.name_address_list) except Exception as ex: write_log(args.log, ex) return ReturnCode.ERROR if not set_address: write_log(args.log, "Address list is empty") return ReturnCode.ERROR set_domain = { email_address[email_address.find("@") + 1:] for email_address in set_address } if sender_domain not in set_domain: return ReturnCode.SENDER_EXTERNAL return ReturnCode.SENDER_INTERNAL
def configure(): hookenv.log('Configuring isc-dhcp') managed_network = IPv4Network(config()["managed-network"]) # We know what network we should be managing. This IPNetwork object has the # following properties: # .ip # Original ip from config value # .network # network ip # .netmmask # .broadcast_address # # What we don't know is what interface this network is connected to. The # following code tries to find out: # 1. what interface is connected to the network # 2. what the ip is of that interface # 3. what other interfaces this network has, ie interfaces that are unmanaged. # 4. what the public ip of the server is # # Then we do two sanity checks: the broadcast and netmask of that interface # must be the same as for the managed network. # mn_iface = None mn_iface_ip = None unmanaged_ifs = [] public_ip = None for interface in netifaces.interfaces(): af_inet = netifaces.ifaddresses(interface).get(AF_INET) if af_inet and af_inet[0].get('broadcast'): addr = IPv4Address(netifaces.ifaddresses(interface)[AF_INET][0]['addr']) if not addr.is_private: # Can't use is_global in 14.04 because of: https://bugs.python.org/issue21386 # We found #4! public_ip = str(addr) if addr in managed_network: # We found #1 and #2 ! mn_iface = interface mn_iface_ip = str(addr) # Sanity check assert(str(managed_network.broadcast_address) == netifaces.ifaddresses(interface)[AF_INET][0]['broadcast']) assert(str(managed_network.netmask) == netifaces.ifaddresses(interface)[AF_INET][0]['netmask']) else: # to find #3 unmanaged_ifs.append(interface) if not public_ip: # No public address found, so we'll use the address of the interface # that is used to connect to the internet. public_ip = get_gateway_source_ip() if not mn_iface: # We are not connected to the network we have to manage. We don't know # what to do in this case so just tell that to the admin. We know this # handler will rerun when the config changes. hookenv.status_set( 'blocked', 'Cannot find interface that is connected to network {}.'.format(managed_network)) return # Now that we know what interface we have to manage, let's check if there is # a dhcp server responding to requests from that interface. If there is no # dhcp server, we should install one. output = subprocess.check_output(['nmap', '--script', 'broadcast-dhcp-discover', '-e', mn_iface], stderr=subprocess.STDOUT, universal_newlines=True) print(output) if 'DHCPOFFER' in output: # pylint: disable=E1135 print('DHCP server found on this network. Will NOT create one.') remove_state('role.dhcp-server') else: print('No DHCP server found on this network, will create one.') set_state('role.dhcp-server') # Configure ourselves as a NAT gateway regardless of network topology so # port-forwarding always works. configure_nat_gateway(mn_iface, unmanaged_ifs) # If our default gateway is not part of the managed network then we must # tell the clients on the managed network that we are their default gateway. # Otherwise, just pass our default gateway to the clients. gateway_if, gateway_ip = get_gateway() if gateway_if != mn_iface: print('Default gateway is NOT in the managed network so we tell potential clients we are their default gateway.') gateway_ip = mn_iface_ip else: print('Default gateway is on the managed network so we pass our default gateway to potential clients.') # Save these values so other handlers can use them. kv = unitdata.kv() kv.set('mn.iface', mn_iface) kv.set('mn.iface-ip', mn_iface_ip) kv.set('mn.gateway', gateway_ip) kv.set('public-ip', public_ip) set_state('gateway.installed') # Now we let the dhcp-server handlers know that they potentially have to # reconfigure their settings. remove_state('dhcp-server.configured')
def allocate( self, *, rid: ID, requested_ns: NetworkServiceSliver, owner_switch: NodeSliver, existing_reservations: List[ABCReservationMixin] ) -> NetworkServiceSliver: """ Allocate Network Service Sliver (Only for L3 Service) - grab the /17 or /48 from BQM Site specific NetworkService - divide it into /24 or /64 subnets - exclude the 1st subnet (reserved for control plane) - exclude the subnets already assigned to other V3/V4 NetworkService on the same owner switch - allocate the first available subnet to the NetworkService :param requested_ns: Requested NetworkService :param owner_switch: BQM Owner site switch identified to serve the NetworkService :param existing_reservations: Existing Reservations which also are served by the owner switch :return NetworkService updated with the allocated subnet for FABNetv4 and FABNetv6 services Return the sliver updated with the subnet """ if requested_ns.get_type( ) != ServiceType.FABNetv4 and requested_ns.get_type( ) != ServiceType.FABNetv6: return requested_ns for ns in owner_switch.network_service_info.network_services.values(): if requested_ns.get_type() == ns.get_type(): # Grab Label Delegations delegation_id, delegated_label = self._get_delegations( lab_cap_delegations=ns.get_label_delegations()) subnet_list = None # Get Subnet if ns.get_type() == ServiceType.FABNetv6: ip_network = IPv6Network(delegated_label.ipv6_subnet) subnet_list = list(ip_network.subnets(new_prefix=64)) elif ns.get_type() == ServiceType.FABNetv4: ip_network = IPv4Network(delegated_label.ipv4_subnet) subnet_list = list(ip_network.subnets(new_prefix=24)) # Exclude the 1st subnet as it is reserved for control plane subnet_list.pop(0) # Exclude the already allocated VLANs and subnets for reservation in existing_reservations: if rid == reservation.get_reservation_id(): continue # For Active or Ticketed or Ticketing reservations; reduce the counts from available allocated_sliver = None if reservation.is_ticketing( ) and reservation.get_approved_resources() is not None: allocated_sliver = reservation.get_approved_resources( ).get_sliver() if (reservation.is_active() or reservation.is_ticketed()) and \ reservation.get_resources() is not None: allocated_sliver = reservation.get_resources( ).get_sliver() self.logger.debug( f"Existing res# {reservation.get_reservation_id()} allocated: {allocated_sliver}" ) if allocated_sliver is None: continue if allocated_sliver.get_type() != requested_ns.get_type(): continue if allocated_sliver.get_type() == ServiceType.FABNetv4: subnet_to_remove = IPv4Network( allocated_sliver.get_gateway().lab.ipv4_subnet) subnet_list.remove(subnet_to_remove) self.logger.debug( f"Excluding already allocated IP4Subnet: " f"{allocated_sliver.get_gateway().lab.ipv4_subnet}" f" to res# {reservation.get_reservation_id()}") elif allocated_sliver.get_gateway( ).lab.ipv6_subnet is not None: subnet_to_remove = IPv6Network( allocated_sliver.get_gateway().lab.ipv6_subnet) subnet_list.remove(subnet_to_remove) self.logger.debug( f"Excluding already allocated IPv6Subnet: " f"{allocated_sliver.get_gateway().lab.ipv6_subnet}" f" to res# {reservation.get_reservation_id()}") gateway_labels = Labels() if requested_ns.get_type() == ServiceType.FABNetv4: gateway_labels.ipv4_subnet = subnet_list[0].with_prefixlen gateway_labels.ipv4 = str(next(subnet_list[0].hosts())) elif requested_ns.get_type() == ServiceType.FABNetv6: gateway_labels.ipv6_subnet = subnet_list[0].with_prefixlen gateway_labels.ipv6 = str(next(subnet_list[0].hosts())) requested_ns.gateway = Gateway(lab=gateway_labels) break return requested_ns
def get_domain_subnets(path="./subnets.yml"): return {k: IPv4Network(v) for k, v in yaml.safe_load(open(path)).items()}
# -*- coding: utf-8 -*- from ipaddress import IPv4Network from ..datasource import DataSource, Dormitory from . import user def init_context(app): app.extensions['gerok_api'] = { 'endpoint': app.config['GEROK_ENDPOINT'], 'token': app.config['GEROK_API_TOKEN'] } datasource = DataSource(name='gerok', user_class=user.User, mail_server="wh17.tu-dresden.de", webmailer_url="https://wh17.tu-dresden.de/webmail/", support_mail="*****@*****.**", init_context=init_context) dormitories = [ Dormitory(name='gerok', display_name="Gerokstraße", datasource=datasource, subnets=[IPv4Network('141.76.124.0/24')]) ]
def set_interface_data(self, ip, netmask, mac): self.ip_addr = ip self.mac_addr = mac n = IPv4Network(ip + "/" + netmask, strict=False) self.broadcast_addr = str(n.broadcast_address)
def test_retrieves_ipv4_ipnetwork_type(self): instance = CidrArrayTestModel(field=['10.1.1.0/24']) instance.save() instance = CidrArrayTestModel.objects.get(id=instance.id) self.assertEqual(instance.field, [IPv4Network('10.1.1.0/24')]) self.assertIsInstance(instance.field[0], IPv4Network)
def validate(self) -> EnsureVPNResult: checker = IPChecker( validation_func=lambda ip: self.wanted_ip.overlaps(IPv4Network(ip)) ) return checker.run()
def ipv4_networks(val: str) -> List[IPv4Network]: return [IPv4Network(s.strip()) for s in val.split(",")]
def __init__(self, ip, mask): try: IPv4Network.__init__(self, (ip, mask), strict=False) except AddressValueError: print("Error generate network")
def verify(openvpn): if openvpn['deleted']: if openvpn['is_bridge_member']: raise ConfigError( (f'Cannot delete interface "{openvpn["intf"]}" as it is a ' f'member of bridge "{openvpn["is_bridge_menber"]}"!')) return None if not openvpn['mode']: raise ConfigError('Must specify OpenVPN operation mode') # Check if we have disabled ncp and at the same time specified ncp-ciphers if openvpn['disable_ncp'] and openvpn['ncp_ciphers']: raise ConfigError( 'Cannot specify both "encryption disable-ncp" and "encryption ncp-ciphers"' ) # # OpenVPN client mode - VERIFY # if openvpn['mode'] == 'client': if openvpn['local_port']: raise ConfigError('Cannot specify "local-port" in client mode') if openvpn['local_host']: raise ConfigError('Cannot specify "local-host" in client mode') if openvpn['protocol'] == 'tcp-passive': raise ConfigError( 'Protocol "tcp-passive" is not valid in client mode') if not openvpn['remote_host']: raise ConfigError('Must specify "remote-host" in client mode') if openvpn['tls_dh'] and openvpn['tls_dh'] != 'none': raise ConfigError('Cannot specify "tls dh-file" in client mode') # # OpenVPN site-to-site - VERIFY # if openvpn['mode'] == 'site-to-site': if openvpn['ncp_ciphers']: raise ConfigError( 'encryption ncp-ciphers cannot be specified in site-to-site mode, only server or client' ) if openvpn['mode'] == 'site-to-site' and not openvpn['is_bridge_member']: if not (openvpn['local_address'] or openvpn['ipv6_local_address']): raise ConfigError( 'Must specify "local-address" or add interface to bridge') if len(openvpn['local_address']) > 1 or len( openvpn['ipv6_local_address']) > 1: raise ConfigError( 'Cannot specify more than 1 IPv4 and 1 IPv6 "local-address"') if len(openvpn['remote_address']) > 1 or len( openvpn['ipv6_remote_address']) > 1: raise ConfigError( 'Cannot specify more than 1 IPv4 and 1 IPv6 "remote-address"') for host in openvpn['remote_host']: if host in openvpn['remote_address'] or host in openvpn[ 'ipv6_remote_address']: raise ConfigError( '"remote-address" cannot be the same as "remote-host"') if openvpn['local_address'] and not (openvpn['remote_address'] or openvpn['local_address_subnet']): raise ConfigError( 'IPv4 "local-address" requires IPv4 "remote-address" or IPv4 "local-address subnet"' ) if openvpn['remote_address'] and not openvpn['local_address']: raise ConfigError( 'IPv4 "remote-address" requires IPv4 "local-address"') if openvpn['ipv6_local_address'] and not openvpn['ipv6_remote_address']: raise ConfigError( 'IPv6 "local-address" requires IPv6 "remote-address"') if openvpn['ipv6_remote_address'] and not openvpn['ipv6_local_address']: raise ConfigError( 'IPv6 "remote-address" requires IPv6 "local-address"') if openvpn['type'] == 'tun': if not (openvpn['remote_address'] or openvpn['ipv6_remote_address']): raise ConfigError('Must specify "remote-address"') if ((openvpn['local_address'] and openvpn['local_address'] == openvpn['remote_address']) or (openvpn['ipv6_local_address'] and openvpn['ipv6_local_address'] == openvpn['ipv6_remote_address'])): raise ConfigError( '"local-address" and "remote-address" cannot be the same') if openvpn['local_host'] in openvpn['local_address'] or openvpn[ 'local_host'] in openvpn['ipv6_local_address']: raise ConfigError( '"local-address" cannot be the same as "local-host"') else: # checks for client-server or site-to-site bridged if openvpn['local_address'] or openvpn['ipv6_local_address'] or openvpn[ 'remote_address'] or openvpn['ipv6_remote_address']: raise ConfigError( 'Cannot specify "local-address" or "remote-address" in client-server or bridge mode' ) # # OpenVPN server mode - VERIFY # if openvpn['mode'] == 'server': if openvpn['protocol'] == 'tcp-active': raise ConfigError( 'Protocol "tcp-active" is not valid in server mode') if openvpn['remote_port']: raise ConfigError('Cannot specify "remote-port" in server mode') if openvpn['remote_host']: raise ConfigError('Cannot specify "remote-host" in server mode') if openvpn['protocol'] == 'tcp-passive' and len( openvpn['remote_host']) > 1: raise ConfigError( 'Cannot specify more than 1 "remote-host" with "tcp-passive"') if not openvpn['tls_dh'] and not checkCertHeader( '-----BEGIN EC PRIVATE KEY-----', openvpn['tls_key']): raise ConfigError( 'Must specify "tls dh-file" when not using EC keys in server mode' ) if len(openvpn['server_subnet']) > 1 or len( openvpn['server_ipv6_subnet']) > 1: raise ConfigError( 'Cannot specify more than 1 IPv4 and 1 IPv6 server subnet') for client in openvpn['client']: if len(client['ip']) > 1 or len(client['ipv6_ip']) > 1: raise ConfigError( f'Server client "{client["name"]}": cannot specify more than 1 IPv4 and 1 IPv6 IP' ) if openvpn['server_subnet']: subnet = IPv4Network(openvpn['server_subnet'][0].replace(' ', '/')) if openvpn['type'] == 'tun' and subnet.prefixlen > 29: raise ConfigError( 'Server subnets smaller than /29 with device type "tun" are not supported' ) elif openvpn['type'] == 'tap' and subnet.prefixlen > 30: raise ConfigError( 'Server subnets smaller than /30 with device type "tap" are not supported' ) for client in openvpn['client']: if client['ip'] and not IPv4Address(client['ip'][0]) in subnet: raise ConfigError( f'Client "{client["name"]}" IP {client["ip"][0]} not in server subnet {subnet}' ) else: if not openvpn['is_bridge_member']: raise ConfigError( 'Must specify "server subnet" or add interface to bridge in server mode' ) if openvpn['server_pool']: if not (openvpn['server_pool_start'] and openvpn['server_pool_stop']): raise ConfigError( 'Server client-ip-pool requires both start and stop addresses in bridged mode' ) else: v4PoolStart = IPv4Address(openvpn['server_pool_start']) v4PoolStop = IPv4Address(openvpn['server_pool_stop']) if v4PoolStart > v4PoolStop: raise ConfigError( f'Server client-ip-pool start address {v4PoolStart} is larger than stop address {v4PoolStop}' ) v4PoolSize = int(v4PoolStop) - int(v4PoolStart) if v4PoolSize >= 65536: raise ConfigError( f'Server client-ip-pool is too large [{v4PoolStart} -> {v4PoolStop} = {v4PoolSize}], maximum is 65536 addresses.' ) v4PoolNets = list( summarize_address_range(v4PoolStart, v4PoolStop)) for client in openvpn['client']: if client['ip']: for v4PoolNet in v4PoolNets: if IPv4Address(client['ip'][0]) in v4PoolNet: print( f'Warning: Client "{client["name"]}" IP {client["ip"][0]} is in server IP pool, it is not reserved for this client.', file=stderr) if openvpn['server_ipv6_subnet']: if not openvpn['server_subnet']: raise ConfigError('IPv6 server requires an IPv4 server subnet') if openvpn['server_ipv6_pool']: if not openvpn['server_pool']: raise ConfigError( 'IPv6 server pool requires an IPv4 server pool') if int(openvpn['server_ipv6_pool_prefixlen']) >= 112: raise ConfigError( 'IPv6 server pool must be larger than /112') v6PoolStart = IPv6Address(openvpn['server_ipv6_pool_base']) v6PoolStop = IPv6Network( (v6PoolStart, openvpn['server_ipv6_pool_prefixlen']), strict=False)[ -1] # don't remove the parentheses, it's a 2-tuple v6PoolSize = int(v6PoolStop) - int(v6PoolStart) if int( openvpn['server_ipv6_pool_prefixlen']) > 96 else 65536 if v6PoolSize < v4PoolSize: raise ConfigError( f'IPv6 server pool must be at least as large as the IPv4 pool (current sizes: IPv6={v6PoolSize} IPv4={v4PoolSize})' ) v6PoolNets = list( summarize_address_range(v6PoolStart, v6PoolStop)) for client in openvpn['client']: if client['ipv6_ip']: for v6PoolNet in v6PoolNets: if IPv6Address(client['ipv6_ip'][0]) in v6PoolNet: print( f'Warning: Client "{client["name"]}" IP {client["ipv6_ip"][0]} is in server IP pool, it is not reserved for this client.', file=stderr) else: if openvpn['server_ipv6_push_route']: raise ConfigError( 'IPv6 push-route requires an IPv6 server subnet') for client in openvpn['client']: if client['ipv6_ip']: raise ConfigError( f'Server client "{client["name"]}" IPv6 IP requires an IPv6 server subnet' ) if client['ipv6_push_route']: raise ConfigError( f'Server client "{client["name"]} IPv6 push-route requires an IPv6 server subnet"' ) if client['ipv6_subnet']: raise ConfigError( f'Server client "{client["name"]} IPv6 subnet requires an IPv6 server subnet"' ) else: # checks for both client and site-to-site go here if openvpn['server_reject_unconfigured']: raise ConfigError( 'reject-unconfigured-clients is only supported in OpenVPN server mode' ) if openvpn['server_topology']: raise ConfigError( 'The "topology" option is only valid in server mode') if (not openvpn['remote_host']) and openvpn['redirect_gateway']: raise ConfigError( 'Cannot set "replace-default-route" without "remote-host"') # # OpenVPN common verification section # not depending on any operation mode # # verify specified IP address is present on any interface on this system if openvpn['local_host']: if not is_addr_assigned(openvpn['local_host']): raise ConfigError( 'No interface on system with specified local-host IP address: {}' .format(openvpn['local_host'])) # TCP active if openvpn['protocol'] == 'tcp-active': if openvpn['local_port']: raise ConfigError('Cannot specify "local-port" with "tcp-active"') if not openvpn['remote_host']: raise ConfigError('Must specify "remote-host" with "tcp-active"') # shared secret and TLS if not (openvpn['shared_secret_file'] or openvpn['tls']): raise ConfigError( 'Must specify one of "shared-secret-key-file" and "tls"') if openvpn['shared_secret_file'] and openvpn['tls']: raise ConfigError( 'Can only specify one of "shared-secret-key-file" and "tls"') if openvpn['mode'] in ['client', 'server']: if not openvpn['tls']: raise ConfigError('Must specify "tls" in client-server mode') # # TLS/encryption # if openvpn['shared_secret_file']: if openvpn['encryption'] in ['aes128gcm', 'aes192gcm', 'aes256gcm']: raise ConfigError( 'GCM encryption with shared-secret-key-file is not supported') if not checkCertHeader('-----BEGIN OpenVPN Static key V1-----', openvpn['shared_secret_file']): raise ConfigError( 'Specified shared-secret-key-file "{}" is not valid'.format( openvpn['shared_secret_file'])) if openvpn['tls']: if not openvpn['tls_ca_cert']: raise ConfigError('Must specify "tls ca-cert-file"') if not (openvpn['mode'] == 'client' and openvpn['auth']): if not openvpn['tls_cert']: raise ConfigError('Must specify "tls cert-file"') if not openvpn['tls_key']: raise ConfigError('Must specify "tls key-file"') if openvpn['tls_auth'] and openvpn['tls_crypt']: raise ConfigError('TLS auth and crypt are mutually exclusive') if not checkCertHeader('-----BEGIN CERTIFICATE-----', openvpn['tls_ca_cert']): raise ConfigError('Specified ca-cert-file "{}" is invalid'.format( openvpn['tls_ca_cert'])) if openvpn['tls_auth']: if not checkCertHeader('-----BEGIN OpenVPN Static key V1-----', openvpn['tls_auth']): raise ConfigError('Specified auth-file "{}" is invalid'.format( openvpn['tls_auth'])) if openvpn['tls_cert']: if not checkCertHeader('-----BEGIN CERTIFICATE-----', openvpn['tls_cert']): raise ConfigError('Specified cert-file "{}" is invalid'.format( openvpn['tls_cert'])) if openvpn['tls_key']: if not checkCertHeader('-----BEGIN (?:RSA |EC )?PRIVATE KEY-----', openvpn['tls_key']): raise ConfigError( 'Specified key-file "{}" is not valid'.format( openvpn['tls_key'])) if openvpn['tls_crypt']: if not checkCertHeader('-----BEGIN OpenVPN Static key V1-----', openvpn['tls_crypt']): raise ConfigError( 'Specified TLS crypt-file "{}" is invalid'.format( openvpn['tls_crypt'])) if openvpn['tls_crl']: if not checkCertHeader('-----BEGIN X509 CRL-----', openvpn['tls_crl']): raise ConfigError('Specified crl-file "{} not valid'.format( openvpn['tls_crl'])) if openvpn['tls_dh'] and openvpn['tls_dh'] != 'none': if not checkCertHeader('-----BEGIN DH PARAMETERS-----', openvpn['tls_dh']): raise ConfigError('Specified dh-file "{}" is not valid'.format( openvpn['tls_dh'])) if openvpn['tls_role']: if openvpn['mode'] in ['client', 'server']: if not openvpn['tls_auth']: raise ConfigError( 'Cannot specify "tls role" in client-server mode') if openvpn['tls_role'] == 'active': if openvpn['protocol'] == 'tcp-passive': raise ConfigError( 'Cannot specify "tcp-passive" when "tls role" is "active"' ) if openvpn['tls_dh'] and openvpn['tls_dh'] != 'none': raise ConfigError( 'Cannot specify "tls dh-file" when "tls role" is "active"' ) elif openvpn['tls_role'] == 'passive': if openvpn['protocol'] == 'tcp-active': raise ConfigError( 'Cannot specify "tcp-active" when "tls role" is "passive"' ) if not openvpn['tls_dh']: raise ConfigError( 'Must specify "tls dh-file" when "tls role" is "passive"' ) if openvpn['tls_key'] and checkCertHeader( '-----BEGIN EC PRIVATE KEY-----', openvpn['tls_key']): if openvpn['tls_dh'] and openvpn['tls_dh'] != 'none': print( 'Warning: using dh-file and EC keys simultaneously will lead to DH ciphers being used instead of ECDH' ) else: print( 'Diffie-Hellman prime file is unspecified, assuming ECDH') # # Auth user/pass # if openvpn['auth']: if not openvpn['auth_user']: raise ConfigError('Username for authentication is missing') if not openvpn['auth_pass']: raise ConfigError('Password for authentication is missing') if openvpn['vrf']: if openvpn['vrf'] not in interfaces(): raise ConfigError(f'VRF "{openvpn["vrf"]}" does not exist') if openvpn['is_bridge_member']: raise ConfigError(( f'Interface "{openvpn["intf"]}" cannot be member of VRF ' f'"{openvpn["vrf"]}" and bridge "{openvpn["is_bridge_member"]}" ' f'at the same time!')) return None
def set_CidrIp(cls, v): return IPv4Network(v, strict=False)