Ejemplo n.º 1
0
def check_network_private(test_network):
    test_net = ipaddress.ip_network(test_network)
    test_start = test_net.network_address
    test_end = test_net.broadcast_address

    for network in settings.vpn.safe_priv_subnets:
        network = ipaddress.ip_network(network)
        net_start = network.network_address
        net_end = network.broadcast_address

        if test_start >= net_start and test_end <= net_end:
            return True

    return False
Ejemplo n.º 2
0
    def add_network_link(self, network, force=False):
        from pritunl import server

        if not force:
            for svr in self.iter_servers(('status', 'groups')):
                if svr.status == ONLINE:
                    raise ServerOnlineError('Server online')

        network = str(ipaddress.ip_network(network))

        self.net_link_collection.update(
            {
                'user_id': self.id,
                'org_id': self.org_id,
                'network': network,
            }, {
                'user_id': self.id,
                'org_id': self.org_id,
                'network': network,
            },
            upsert=True)

        if force:
            for svr in self.iter_servers(server.operation_fields):
                if svr.status == ONLINE:
                    logger.info(
                        'Restarting running server to add network link',
                        'user',
                    )
                    svr.restart()
Ejemplo n.º 3
0
def find_interface(network):
    network = ipaddress.ip_network(network, strict=False)

    for interface, data in list(get_interfaces().items()):
        try:
            address = ipaddress.ip_address(data['address'])
        except ValueError:
            continue

        if address in network and data['netmask'] == str(network.netmask):
            return data
Ejemplo n.º 4
0
    def add_route(self, network):
        try:
            network = str(ipaddress.ip_network(network))
        except ValueError:
            raise NetworkInvalid('Network address is invalid')

        network_id = hashlib.md5(network.encode()).hexdigest()
        self.routes[network_id] = {
            'network': network,
        }

        return network_id
Ejemplo n.º 5
0
def check_network_range(test_network, start_addr, end_addr):
    test_net = ipaddress.ip_network(test_network)
    start_addr = ipaddress.ip_address(start_addr)
    end_addr = ipaddress.ip_address(end_addr)

    return all((
        start_addr != test_net.network_address,
        end_addr != test_net.broadcast_address,
        start_addr < end_addr,
        start_addr in test_net,
        end_addr in test_net,
    ))
Ejemplo n.º 6
0
    def _check_whitelist(self):
        if settings.app.sso_whitelist:
            remote_ip = ipaddress.ip_address(self.remote_ip)

            for network_str in settings.app.sso_whitelist:
                try:
                    network = ipaddress.ip_network(network_str)
                except (ipaddress.AddressValueError, ValueError):
                    logger.warning(
                        'Invalid whitelist network',
                        'authorize',
                        network=network_str,
                    )
                    continue

                if remote_ip in network:
                    self.whitelisted = True
                    break
Ejemplo n.º 7
0
def check_network_overlap(test_network, networks):
    test_net = ipaddress.ip_network(test_network)
    test_start = test_net.network_address
    test_end = test_net.broadcast_address

    for network in networks:
        net_start = network.network_address
        net_end = network.broadcast_address

        if test_start >= net_start and test_start <= net_end:
            return True
        elif test_end >= net_start and test_end <= net_end:
            return True
        elif net_start >= test_start and net_start <= test_end:
            return True
        elif net_end >= test_start and net_end <= test_end:
            return True

    return False
Ejemplo n.º 8
0
def multi_get_ip_addr(org_id, user_ids):
    spec = {
        'user_id': {'$in': user_ids},
    }
    project = {
        '_id': False,
        'user_id': True,
        'server_id': True,
        'address': True,
    }

    for doc in ServerIpPool.collection.find(spec, project):
        network = ipaddress.ip_network(doc['address'], strict=False)
        network = str(network.network_address) + '/' + str(network.prefixlen)
        addr6 = utils.ip4to6x64(settings.vpn.ipv6_prefix,
            network, doc['address'])

        yield doc['user_id'], doc['server_id'], \
            doc['address'].split('/')[0], addr6.split('/')[0]
Ejemplo n.º 9
0
def get_used_resources(ignore_server_id):
    response = Server.collection.aggregate(([
        {
            '$match': {
                '_id': {
                    '$ne': ignore_server_id
                },
            }
        },
    ] if ignore_server_id else []) + [
        {
            '$project': {
                'network': True,
                'network_wg': True,
                'interface': True,
                'port_protocol': {
                    '$concat': [
                        {
                            '$substr': ['$port', 0, 5]
                        },
                        '$protocol',
                    ]
                },
                'port_protocol_wg': {
                    '$concat': [
                        {
                            '$substr': ['$port_wg', 0, 5]
                        },
                        'udp',
                    ]
                },
            }
        },
        {
            '$group': {
                '_id': None,
                'networks': {
                    '$addToSet': '$network'
                },
                'networks_wg': {
                    '$addToSet': '$network_wg'
                },
                'interfaces': {
                    '$addToSet': '$interface'
                },
                'ports': {
                    '$addToSet': '$port_protocol'
                },
                'ports_wg': {
                    '$addToSet': '$port_protocol_wg'
                },
            }
        },
    ])

    used_resources = None
    for used_resources in response:
        break

    if used_resources:
        used_resources.pop('_id')
    else:
        used_resources = {
            'networks': set(),
            'networks_wg': set(),
            'interfaces': set(),
            'ports': set(),
            'ports_wg': set(),
        }

    ports = set(used_resources['ports'] or [])
    ports_wg = set([_f for _f in used_resources['ports_wg'] if _f])
    try:
        ports_wg.remove('udp')
    except KeyError:
        pass
    ports = ports.union(ports_wg)

    networks = set(used_resources['networks'] or [])
    networks_wg = set([_f for _f in used_resources['networks_wg'] if _f])
    networks = networks.union(networks_wg)

    return {
        'networks': {ipaddress.ip_network(x, strict=False)
                     for x in networks},
        'interfaces': set(used_resources['interfaces'] or []),
        'ports': ports,
    }
Ejemplo n.º 10
0
def user_put(org_id, user_id):
    if settings.app.demo_mode:
        return utils.demo_blocked()

    org = organization.get_by_id(org_id)
    user = org.get_user(user_id)
    reset_user = False
    reset_user_cache = False
    port_forwarding_event = False
    remote_addr = utils.get_remote_addr()

    if 'name' in flask.request.json:
        name = utils.filter_str(flask.request.json['name']) or 'undefined'

        if name != user.name:
            user.audit_event(
                'user_updated',
                'User name changed',
                remote_addr=remote_addr,
            )

            journal.entry(
                journal.USER_UPDATE,
                user.journal_data,
                event_long='User name changed',
                remote_address=remote_addr,
            )

        user.name = name

    if 'email' in flask.request.json:
        email = utils.filter_str(flask.request.json['email']) or None

        if email != user.email:
            user.audit_event(
                'user_updated',
                'User email changed',
                remote_addr=remote_addr,
            )

            journal.entry(
                journal.USER_UPDATE,
                user.journal_data,
                event_long='User email changed',
                remote_address=remote_addr,
            )

        user.email = email

    if 'auth_type' in flask.request.json:
        auth_type = utils.filter_str(flask.request.json['auth_type']) or None

        if auth_type in AUTH_TYPES:
            if auth_type != user.auth_type:
                reset_user = True
                reset_user_cache = True
            user.auth_type = auth_type

    if 'yubico_id' in flask.request.json:
        yubico_id = utils.filter_str(flask.request.json['yubico_id']) or None
        yubico_id = yubico_id[:12] if yubico_id else None
        if yubico_id != user.yubico_id:
            reset_user = True
            reset_user_cache = True
        user.yubico_id = yubico_id

    if 'groups' in flask.request.json:
        groups = flask.request.json['groups'] or []
        for i, group in enumerate(groups):
            groups[i] = utils.filter_str(group)
        groups = set(groups)

        if groups != set(user.groups or []):
            user.audit_event(
                'user_updated',
                'User groups changed',
                remote_addr=remote_addr,
            )

            journal.entry(
                journal.USER_UPDATE,
                user.journal_data,
                event_long='User groups changed',
                remote_address=remote_addr,
            )

        user.groups = list(groups)

    if 'pin' in flask.request.json:
        pin = flask.request.json['pin'] or None

        if pin is not True:
            if pin:
                if settings.user.pin_mode == PIN_DISABLED:
                    return utils.jsonify(
                        {
                            'error': PIN_IS_DISABLED,
                            'error_msg': PIN_IS_DISABLED_MSG,
                        }, 400)

                if RADIUS_AUTH in user.auth_type:
                    return utils.jsonify(
                        {
                            'error': PIN_RADIUS,
                            'error_msg': PIN_RADIUS_MSG,
                        }, 400)

                if settings.user.pin_digits_only and not pin.isdigit():
                    return utils.jsonify(
                        {
                            'error': PIN_NOT_DIGITS,
                            'error_msg': PIN_NOT_DIGITS_MSG,
                        }, 400)

                if len(pin) < settings.user.pin_min_length:
                    return utils.jsonify(
                        {
                            'error': PIN_TOO_SHORT,
                            'error_msg': PIN_TOO_SHORT_MSG,
                        }, 400)

            if user.set_pin(pin):
                reset_user = True
                reset_user_cache = True

                user.audit_event(
                    'user_updated',
                    'User pin changed',
                    remote_addr=remote_addr,
                )

                journal.entry(
                    journal.USER_UPDATE,
                    user.journal_data,
                    event_long='User pin changed',
                    remote_address=remote_addr,
                )

    if 'network_links' in flask.request.json:
        network_links_cur = set(user.get_network_links())
        network_links_new = set()

        for network_link in flask.request.json['network_links'] or []:
            try:
                network_link = str(ipaddress.ip_network(network_link))
            except (ipaddress.AddressValueError, ValueError):
                return _network_link_invalid()
            network_links_new.add(network_link)

        network_links_add = network_links_new - network_links_cur
        network_links_rem = network_links_cur - network_links_new

        if len(network_links_add) or len(network_links_rem):
            reset_user = True
            user.audit_event(
                'user_updated',
                'User network links updated',
                remote_addr=remote_addr,
            )

            journal.entry(
                journal.USER_UPDATE,
                user.journal_data,
                event_long='User network links updated',
                remote_address=remote_addr,
            )

        try:
            for network_link in network_links_add:
                user.add_network_link(network_link)
        except ServerOnlineError:
            return utils.jsonify(
                {
                    'error': NETWORK_LINK_NOT_OFFLINE,
                    'error_msg': NETWORK_LINK_NOT_OFFLINE_MSG,
                }, 400)

        for network_link in network_links_rem:
            user.remove_network_link(network_link)

    if 'port_forwarding' in flask.request.json:
        port_forwarding = []
        for data in flask.request.json['port_forwarding'] or []:
            port_forwarding.append({
                'protocol':
                utils.filter_str(data.get('protocol')),
                'port':
                utils.filter_str(data.get('port')),
                'dport':
                utils.filter_str(data.get('dport')),
            })

        if port_forwarding != user.port_forwarding:
            port_forwarding_event = True
            user.audit_event(
                'user_updated',
                'User port forwarding changed',
                remote_addr=remote_addr,
            )

            journal.entry(
                journal.USER_UPDATE,
                user.journal_data,
                event_long='User port forwarding changed',
                remote_address=remote_addr,
            )

        user.port_forwarding = port_forwarding

    disabled = True if flask.request.json.get('disabled') else False
    if disabled != user.disabled:
        user.audit_event(
            'user_updated',
            'User %s' % ('disabled' if disabled else 'enabled'),
            remote_addr=remote_addr,
        )

        journal.entry(
            journal.USER_UPDATE,
            user.journal_data,
            event_long='User %s' % ('disabled' if disabled else 'enabled'),
            remote_address=remote_addr,
        )

        if disabled:
            reset_user = True
            reset_user_cache = True
    user.disabled = disabled

    user.bypass_secondary = True if flask.request.json.get(
        'bypass_secondary') else False

    user.client_to_client = True if flask.request.json.get(
        'client_to_client') else False

    if user.bypass_secondary:
        if user.pin:
            return utils.jsonify(
                {
                    'error': PIN_BYPASS_SECONDARY,
                    'error_msg': PIN_BYPASS_SECONDARY_MSG,
                }, 400)
        if user.yubico_id:
            return utils.jsonify(
                {
                    'error': YUBIKEY_BYPASS_SECONDARY,
                    'error_msg': YUBIKEY_BYPASS_SECONDARY_MSG,
                }, 400)

    if 'mac_addresses' in flask.request.json:
        mac_addresses = flask.request.json['mac_addresses'] or None
        if user.mac_addresses != mac_addresses:
            user.audit_event(
                'user_updated',
                'User mac addresses changed',
                remote_addr=remote_addr,
            )

            journal.entry(
                journal.USER_UPDATE,
                user.journal_data,
                event_long='User mac addresses changed',
                remote_address=remote_addr,
            )

            reset_user = True
        user.mac_addresses = mac_addresses

    if 'dns_servers' in flask.request.json:
        dns_servers = flask.request.json['dns_servers'] or None
        if user.dns_servers != dns_servers:
            user.audit_event(
                'user_updated',
                'User dns servers changed',
                remote_addr=remote_addr,
            )

            journal.entry(
                journal.USER_UPDATE,
                user.journal_data,
                event_long='User dns servers changed',
                remote_address=remote_addr,
            )

            reset_user = True
        user.dns_servers = dns_servers

    if 'dns_suffix' in flask.request.json:
        dns_suffix = utils.filter_str(flask.request.json['dns_suffix']) or None
        if user.dns_suffix != dns_suffix:
            user.audit_event(
                'user_updated',
                'User dns suffix changed',
                remote_addr=remote_addr,
            )

            journal.entry(
                journal.USER_UPDATE,
                user.journal_data,
                event_long='User dns suffix changed',
                remote_address=remote_addr,
            )

            reset_user = True
        user.dns_suffix = dns_suffix

    user.commit()
    event.Event(type=USERS_UPDATED, resource_id=user.org.id)
    if port_forwarding_event:
        messenger.publish('port_forwarding', {
            'org_id': org.id,
            'user_id': user.id,
        })

    if reset_user_cache:
        user.clear_auth_cache()
    if reset_user:
        user.disconnect()

    send_key_email = flask.request.json.get('send_key_email')
    if send_key_email and user.email:
        user.audit_event(
            'user_emailed',
            'User key email sent to "%s"' % user.email,
            remote_addr=remote_addr,
        )

        journal.entry(
            journal.USER_PROFILE_EMAIL,
            user.journal_data,
            event_long='User key email sent to "%s"' % user.email,
            remote_address=remote_addr,
        )

        try:
            user.send_key_email(utils.get_url_root())
        except EmailNotConfiguredError:
            return utils.jsonify(
                {
                    'error': EMAIL_NOT_CONFIGURED,
                    'error_msg': EMAIL_NOT_CONFIGURED_MSG,
                }, 400)
        except EmailFromInvalid:
            return utils.jsonify(
                {
                    'error': EMAIL_FROM_INVALID,
                    'error_msg': EMAIL_FROM_INVALID_MSG,
                }, 400)
        except EmailAuthInvalid:
            return utils.jsonify(
                {
                    'error': EMAIL_AUTH_INVALID,
                    'error_msg': EMAIL_AUTH_INVALID_MSG,
                }, 400)

    return utils.jsonify(user.dict())
Ejemplo n.º 11
0
def get_network_gateway_cidr(network):
    network = ipaddress.ip_network(network, strict=False)
    cidr = network.prefixlen
    return str(next(network.hosts())) + '/' + str(cidr)
Ejemplo n.º 12
0
def get_network_gateway(network):
    return str(next(ipaddress.ip_network(network).hosts()))
Ejemplo n.º 13
0
def parse_network(network):
    address = ipaddress.ip_network(network, strict=False)
    return str(address.network_address), str(address.netmask)
Ejemplo n.º 14
0
def server_put_post(server_id=None):
    if settings.app.demo_mode:
        return utils.demo_blocked()

    used_resources = server.get_used_resources(server_id)
    network_used = used_resources['networks']
    port_used = used_resources['ports']

    name = None
    name_def = False
    if 'name' in flask.request.json:
        name_def = True
        name = utils.filter_str(flask.request.json['name'])

    network = None
    network_def = False
    if 'network' in flask.request.json and \
            flask.request.json['network'] != '':
        network_def = True
        network = flask.request.json['network'].strip()

        try:
            if not _check_network_private(network):
                return _network_invalid()
        except (ipaddress.AddressValueError, ValueError):
            return _network_invalid()

    wg = None
    wg_def = False
    if 'wg' in flask.request.json:
        wg_def = True
        wg = True if flask.request.json['wg'] else False

    network_wg = None
    network_wg_def = False
    if wg and 'network_wg' in flask.request.json and \
            flask.request.json['network_wg'] != '':
        network_wg_def = True
        network_wg = flask.request.json['network_wg'].strip()

        try:
            if not _check_network_private(network_wg):
                return _network_wg_invalid()
        except (ipaddress.AddressValueError, ValueError):
            return _network_wg_invalid()
    elif not wg:
        network_wg_def = True

    network_mode = None
    network_mode_def = False
    if 'network_mode' in flask.request.json:
        network_mode_def = True
        network_mode = flask.request.json['network_mode']

    network_start = None
    network_start_def = False
    if 'network_start' in flask.request.json:
        network_start_def = True
        network_start = flask.request.json['network_start']

    network_end = None
    network_end_def = False
    if 'network_end' in flask.request.json:
        network_end_def = True
        network_end = flask.request.json['network_end']

    restrict_routes = None
    restrict_routes_def = False
    if 'restrict_routes' in flask.request.json:
        restrict_routes_def = True
        restrict_routes = True if flask.request.json['restrict_routes'] \
            else False

    ipv6 = None
    ipv6_def = False
    if 'ipv6' in flask.request.json:
        ipv6_def = True
        ipv6 = True if flask.request.json['ipv6'] else False

    ipv6_firewall = None
    ipv6_firewall_def = False
    if 'ipv6_firewall' in flask.request.json:
        ipv6_firewall_def = True
        ipv6_firewall = True if flask.request.json['ipv6_firewall'] else False

    bind_address = None
    bind_address_def = False
    if 'bind_address' in flask.request.json:
        bind_address_def = True
        bind_address = utils.filter_str(flask.request.json['bind_address'])

    protocol = 'udp'
    protocol_def = False
    if 'protocol' in flask.request.json:
        protocol_def = True
        protocol = flask.request.json['protocol'].lower()

        if protocol not in ('udp', 'tcp'):
            return utils.jsonify(
                {
                    'error': PROTOCOL_INVALID,
                    'error_msg': PROTOCOL_INVALID_MSG,
                }, 400)

    port = None
    port_def = False
    if 'port' in flask.request.json and flask.request.json['port'] != 0:
        port_def = True
        port = flask.request.json['port']

        try:
            port = int(port)
        except ValueError:
            return _port_invalid()

        if port < 1 or port > 65535:
            return _port_invalid()

    port_wg = None
    port_wg_def = False
    if wg and 'port_wg' in flask.request.json and \
            flask.request.json['port_wg'] != 0:
        port_wg_def = True
        port_wg = flask.request.json['port_wg']

        try:
            port_wg = int(port_wg)
        except ValueError:
            return _port_wg_invalid()

        if port_wg < 1 or port_wg > 65535:
            return _port_wg_invalid()
    elif not wg:
        port_wg_def = True

    dh_param_bits = None
    dh_param_bits_def = False
    if flask.request.json.get('dh_param_bits'):
        dh_param_bits_def = True
        dh_param_bits = flask.request.json['dh_param_bits']

        try:
            dh_param_bits = int(dh_param_bits)
        except ValueError:
            return _dh_param_bits_invalid()

        if dh_param_bits not in VALID_DH_PARAM_BITS:
            return _dh_param_bits_invalid()

    groups = None
    groups_def = False
    if 'groups' in flask.request.json:
        groups_def = True
        groups = flask.request.json['groups'] or []
        for i, group in enumerate(groups):
            groups[i] = utils.filter_str(group)
        groups = list(set(groups))

    multi_device = False
    multi_device_def = False
    if 'multi_device' in flask.request.json:
        multi_device_def = True
        multi_device = True if flask.request.json['multi_device'] else False

    dns_servers = None
    dns_servers_def = False
    if 'dns_servers' in flask.request.json:
        dns_servers_def = True
        dns_servers = flask.request.json['dns_servers'] or []

        for dns_server in dns_servers:
            try:
                ipaddress.ip_address(dns_server)
            except (ipaddress.AddressValueError, ValueError):
                return _dns_server_invalid()

    search_domain = None
    search_domain_def = False
    if 'search_domain' in flask.request.json:
        search_domain_def = True
        search_domain = flask.request.json['search_domain']
        if search_domain:
            search_domain = ', '.join([
                utils.filter_str(x.strip()) for x in search_domain.split(',')
            ])
        else:
            search_domain = None

    inter_client = True
    inter_client_def = False
    if 'inter_client' in flask.request.json:
        inter_client_def = True
        inter_client = True if flask.request.json['inter_client'] else False

    ping_interval = None
    ping_interval_def = False
    if 'ping_interval' in flask.request.json:
        ping_interval_def = True
        ping_interval = int(flask.request.json['ping_interval'] or 10)

    ping_timeout = None
    ping_timeout_def = False
    if 'ping_timeout' in flask.request.json:
        ping_timeout_def = True
        ping_timeout = int(flask.request.json['ping_timeout'] or 60)

    link_ping_interval = None
    link_ping_interval_def = False
    if 'link_ping_interval' in flask.request.json:
        link_ping_interval_def = True
        link_ping_interval = int(flask.request.json['link_ping_interval'] or 1)

    link_ping_timeout = None
    link_ping_timeout_def = False
    if 'link_ping_timeout' in flask.request.json:
        link_ping_timeout_def = True
        link_ping_timeout = int(flask.request.json['link_ping_timeout'] or 5)

    inactive_timeout = None
    inactive_timeout_def = False
    if 'inactive_timeout' in flask.request.json:
        inactive_timeout_def = True
        inactive_timeout = int(flask.request.json['inactive_timeout']
                               or 0) or None

    session_timeout = None
    session_timeout_def = False
    if 'session_timeout' in flask.request.json:
        session_timeout_def = True
        session_timeout = int(flask.request.json['session_timeout']
                              or 0) or None

    allowed_devices = None
    allowed_devices_def = False
    if 'allowed_devices' in flask.request.json:
        allowed_devices_def = True
        allowed_devices = flask.request.json['allowed_devices'] or None

    max_clients = None
    max_clients_def = False
    if 'max_clients' in flask.request.json:
        max_clients_def = True
        max_clients = flask.request.json['max_clients']
        if max_clients:
            max_clients = int(max_clients)
        else:
            max_clients = 2000

    max_devices = None
    max_devices_def = False
    if 'max_devices' in flask.request.json:
        max_devices_def = True
        max_devices = flask.request.json['max_devices']
        if max_devices:
            max_devices = int(max_devices)
        else:
            max_devices = 0

    replica_count = None
    replica_count_def = False
    if 'replica_count' in flask.request.json:
        replica_count_def = True
        replica_count = flask.request.json['replica_count']
        if replica_count:
            replica_count = int(replica_count)
        if not replica_count:
            replica_count = 1

    vxlan = True
    vxlan_def = False
    if 'vxlan' in flask.request.json:
        vxlan_def = True
        vxlan = True if flask.request.json['vxlan'] else False

    dns_mapping = False
    dns_mapping_def = False
    if 'dns_mapping' in flask.request.json:
        dns_mapping_def = True
        dns_mapping = True if flask.request.json['dns_mapping'] else False

    debug = False
    debug_def = False
    if 'debug' in flask.request.json:
        debug_def = True
        debug = True if flask.request.json['debug'] else False

    pre_connect_msg = None
    pre_connect_msg_def = False
    if 'pre_connect_msg' in flask.request.json:
        pre_connect_msg_def = True
        if flask.request.json['pre_connect_msg']:
            pre_connect_msg = flask.request.json['pre_connect_msg'].strip()

    otp_auth = False
    otp_auth_def = False
    if 'otp_auth' in flask.request.json:
        otp_auth_def = True
        otp_auth = True if flask.request.json['otp_auth'] else False

    mss_fix = None
    mss_fix_def = False
    if 'mss_fix' in flask.request.json:
        mss_fix_def = True
        mss_fix = flask.request.json['mss_fix'] or None
        if mss_fix:
            mss_fix = int(mss_fix) or None

    lzo_compression = False
    lzo_compression_def = False
    if 'lzo_compression' in flask.request.json:
        lzo_compression_def = True
        lzo_compression = True if flask.request.json[
            'lzo_compression'] else False

    cipher = None
    cipher_def = False
    if 'cipher' in flask.request.json:
        cipher_def = True
        cipher = flask.request.json['cipher']

        if cipher not in CIPHERS:
            return utils.jsonify(
                {
                    'error': CIPHER_INVALID,
                    'error_msg': CIPHER_INVALID_MSG,
                }, 400)

    hash = None
    hash_def = False
    if 'hash' in flask.request.json:
        hash_def = True
        hash = flask.request.json['hash']

        if hash not in HASHES:
            return utils.jsonify(
                {
                    'error': HASH_INVALID,
                    'error_msg': HASH_INVALID_MSG,
                }, 400)

    block_outside_dns = False
    block_outside_dns_def = False
    if 'block_outside_dns' in flask.request.json:
        block_outside_dns_def = True
        block_outside_dns = True if flask.request.json[
            'block_outside_dns'] else False

    jumbo_frames = False
    jumbo_frames_def = False
    if 'jumbo_frames' in flask.request.json:
        jumbo_frames_def = True
        jumbo_frames = True if flask.request.json['jumbo_frames'] else False

    if not server_id:
        if not name_def:
            return utils.jsonify(
                {
                    'error': MISSING_PARAMS,
                    'error_msg': MISSING_PARAMS_MSG,
                }, 400)

        if not network_def:
            network_def = True
            rand_range = list(range(215, 250))
            rand_range_low = list(range(15, 215))
            random.shuffle(rand_range)
            random.shuffle(rand_range_low)
            rand_range += rand_range_low
            for i in rand_range:
                rand_network = '192.168.%s.0/24' % i
                if not _check_network_overlap(rand_network, network_used):
                    network = rand_network
                    break
            if not network:
                return utils.jsonify(
                    {
                        'error': NETWORK_IN_USE,
                        'error_msg': NETWORK_IN_USE_MSG,
                    }, 400)

        if wg and not network_wg_def:
            network_used.add(ipaddress.ip_network(network))

            network_wg_def = True
            rand_range = list(range(215, 250))
            rand_range_low = list(range(15, 215))
            random.shuffle(rand_range)
            random.shuffle(rand_range_low)
            rand_range += rand_range_low
            for i in rand_range:
                rand_network_wg = '192.168.%s.0/24' % i
                if not _check_network_overlap(rand_network_wg, network_used):
                    network_wg = rand_network_wg
                    break
            if not network_wg:
                return utils.jsonify(
                    {
                        'error': NETWORK_WG_IN_USE,
                        'error_msg': NETWORK_WG_IN_USE_MSG,
                    }, 400)

        if not port_def:
            port_def = True
            rand_ports = list(range(10000, 19999))
            random.shuffle(rand_ports)
            for rand_port in rand_ports:
                if '%s%s' % (rand_port, protocol) not in port_used:
                    port = rand_port
                    break
            if not port:
                return utils.jsonify(
                    {
                        'error': PORT_PROTOCOL_IN_USE,
                        'error_msg': PORT_PROTOCOL_IN_USE_MSG,
                    }, 400)

        if wg and not port_wg_def:
            port_used.add(port)

            port_wg_def = True
            rand_port_wgs = list(range(10000, 19999))
            random.shuffle(rand_port_wgs)
            for rand_port_wg in rand_port_wgs:
                if '%s%s' % (rand_port_wg, protocol) not in port_used:
                    port_wg = rand_port_wg
                    break
            if not port_wg:
                return utils.jsonify(
                    {
                        'error': PORT_WG_IN_USE,
                        'error_msg': PORT_WG_IN_USE_MSG,
                    }, 400)

        if not dh_param_bits_def:
            dh_param_bits_def = True
            dh_param_bits = settings.vpn.default_dh_param_bits

    changed = None

    if not server_id:
        svr = server.new_server(
            name=name,
            network=network,
            network_wg=network_wg,
            groups=groups,
            network_mode=network_mode,
            network_start=network_start,
            network_end=network_end,
            restrict_routes=restrict_routes,
            wg=wg,
            ipv6=ipv6,
            ipv6_firewall=ipv6_firewall,
            bind_address=bind_address,
            port=port,
            port_wg=port_wg,
            protocol=protocol,
            dh_param_bits=dh_param_bits,
            multi_device=multi_device,
            dns_servers=dns_servers,
            search_domain=search_domain,
            otp_auth=otp_auth,
            cipher=cipher,
            hash=hash,
            block_outside_dns=block_outside_dns,
            jumbo_frames=jumbo_frames,
            lzo_compression=lzo_compression,
            inter_client=inter_client,
            ping_interval=ping_interval,
            ping_timeout=ping_timeout,
            link_ping_interval=link_ping_interval,
            link_ping_timeout=link_ping_timeout,
            inactive_timeout=inactive_timeout,
            session_timeout=session_timeout,
            allowed_devices=allowed_devices,
            max_clients=max_clients,
            max_devices=max_devices,
            replica_count=replica_count,
            vxlan=vxlan,
            dns_mapping=dns_mapping,
            debug=debug,
            pre_connect_msg=pre_connect_msg,
            mss_fix=mss_fix,
        )
        svr.add_host(settings.local.host_id)
    else:
        svr = server.get_by_id(server_id)

        if name_def:
            svr.name = name
        if network_def:
            svr.network = network
        if network_wg_def:
            svr.network_wg = network_wg
        if groups_def:
            svr.groups = groups
        if network_start_def:
            svr.network_start = network_start
        if network_end_def:
            svr.network_end = network_end
        if restrict_routes_def:
            svr.restrict_routes = restrict_routes
        if wg_def:
            svr.wg = wg
        if ipv6_def:
            svr.ipv6 = ipv6
        if ipv6_firewall_def:
            svr.ipv6_firewall = ipv6_firewall
        if network_mode_def:
            svr.network_mode = network_mode
        if bind_address_def:
            svr.bind_address = bind_address
        if port_def:
            svr.port = port
        if port_wg_def:
            svr.port_wg = port_wg
        if protocol_def:
            svr.protocol = protocol
        if dh_param_bits_def and svr.dh_param_bits != dh_param_bits:
            svr.dh_param_bits = dh_param_bits
            svr.generate_dh_param()
        if multi_device_def:
            svr.multi_device = multi_device
        if dns_servers_def:
            svr.dns_servers = dns_servers
        if search_domain_def:
            svr.search_domain = search_domain
        if otp_auth_def:
            svr.otp_auth = otp_auth
        if cipher_def:
            svr.cipher = cipher
        if hash_def:
            svr.hash = hash
        if block_outside_dns_def:
            svr.block_outside_dns = block_outside_dns
        if jumbo_frames_def:
            svr.jumbo_frames = jumbo_frames
        if lzo_compression_def:
            svr.lzo_compression = lzo_compression
        if inter_client_def:
            svr.inter_client = inter_client
        if ping_interval_def:
            svr.ping_interval = ping_interval
        if ping_timeout_def:
            svr.ping_timeout = ping_timeout
        if link_ping_interval_def:
            svr.link_ping_interval = link_ping_interval
        if link_ping_timeout_def:
            svr.link_ping_timeout = link_ping_timeout
        if inactive_timeout_def:
            svr.inactive_timeout = inactive_timeout
        if session_timeout_def:
            svr.session_timeout = session_timeout
        if allowed_devices_def:
            svr.allowed_devices = allowed_devices
        if max_clients_def:
            svr.max_clients = max_clients
        if max_devices_def:
            svr.max_devices = max_devices
        if replica_count_def:
            svr.replica_count = replica_count
        if vxlan_def:
            svr.vxlan = vxlan
        if dns_mapping_def:
            svr.dns_mapping = dns_mapping
        if debug_def:
            svr.debug = debug
        if pre_connect_msg_def:
            svr.pre_connect_msg = pre_connect_msg
        if mss_fix_def:
            svr.mss_fix = mss_fix

        changed = svr.changed

    svr.generate_auth_key()

    err, err_msg = svr.validate_conf()
    if err:
        return utils.jsonify({
            'error': err,
            'error_msg': err_msg,
        }, 400)

    svr.commit(changed)

    if not server_id:
        logger.LogEntry(message='Created server "%s".' % svr.name)

    event.Event(type=SERVERS_UPDATED)
    event.Event(type=SERVER_ROUTES_UPDATED, resource_id=svr.id)
    for org in svr.iter_orgs():
        event.Event(type=USERS_UPDATED, resource_id=org.id)
    return utils.jsonify(svr.dict())