def add_firewall_rule(fw_rule): # ensuring all necessary fields are present in the namespace before continuing. valid_fields = [ 'action', 'dst_ip', 'dst_netmask', 'dst_port', 'position', 'protocol', 'src_ip', 'src_netmask', 'tab', 'zone' ] if not all([hasattr(fw_rule, x) for x in valid_fields]): raise ValidationError('Invalid form.') # grabbing list of configured iptable rules for the specified chain. output = run(f'sudo iptables -nL {fw_rule.zone} --line-number', shell=True, capture_output=True).stdout.splitlines()[1:] rule_count = len(output) fw_rule.position = convert_int(fw_rule.position) if (not rule_count and fw_rule.position != 1): raise ValidationError('First firewall rule must have position 1.') if (not 0 < fw_rule.position <= rule_count + 1): raise ValidationError( f'Position outside of valid range. (1-{rule_count+1})') if (fw_rule.protocol not in ['any', 'tcp', 'udp', 'icmp']): raise ValidationError('Network protocol is not valid.') if (fw_rule.protocol in ['any', 'icmp'] and fw_rule.dst_port): raise ValidationError('Only TCP/UDP use destination port field.')
def syslog_dropdown(syslog_time): syslog_time = convert_int(syslog_time) if (syslog_time): raise ValidationError('Dropdown values must be an integer.') if (syslog_time not in [5, 10, 60]): raise ValidationError('Dropdown values can only be 5, 10, or 60.')
def log_settings(log_settings): if (log_settings['length'] not in [30, 45, 60, 90]): raise ValidationError('Log settings are not valid.') try: LOG(log_settings['level']) except ValueError: raise ValidationError('Log settings are not valid.')
def dns_record_remove(dns_record_name): dns_server = load_configuration('dns_server')['dns_server'] if (dns_record_name == 'dnx.firewall'): raise ValidationError('Cannot remove dnxfirewall dns record.') if (dns_record_name not in dns_server['records']): raise ValidationError(INVALID_FORM)
def main_services(services_form): valid_services = ['dnx-dns-proxy', 'dnx-fw-proxy', 'dnx-dhcp-server', 'dnx-updates'] service = services_form['service'] ruleset = services_form['ruleset'] if (service not in valid_services): raise ValidationError(INVALID_FORM) if (service in ['dnx-dns-proxy', 'dnx-ip-proxy'] and ruleset is None): raise ValidationError(INVALID_FORM)
def domain_category_keywords(categories): dns_proxy = load_configuration('dns_proxy')['dns_proxy'] domain_cats = dns_proxy['categories']['default'] for cat in categories: if (cat not in domain_cats): raise ValidationError(INVALID_FORM) if (not domain_cats[cat]['enabled']): raise ValidationError(INVALID_FORM)
def portscan_settings(portscan_settings): ips = load_configuration('ips')['ips'] current_prevention = ips['port_scan']['enabled'] for item in portscan_settings: if (item not in ['enabled', 'reject']): raise ValidationError(INVALID_FORM) if ('reject' in portscan_settings and 'drop' not in portscan_settings and not current_prevention): raise ValidationError('Prevention must be enabled to configure portscan reject.')
def dns_over_tls(dns_tls_settings): dns_server = load_configuration('dns_server')['dns_server'] current_tls = dns_server['tls']['enabled'] for item in dns_tls_settings['enabled']: if (item not in ['dns_over_tls', 'udp_fallback']): raise ValidationError(INVALID_FORM) # NOTE: current_tls shouldnt matter since tls will be in form if enabled regardless if (not current_tls and 'udp_fallback' in dns_tls_settings['enabled'] and 'dns_over_tls' not in dns_tls_settings['enabled']): raise ValidationError('DNS over TLS must be enabled to configure UDP fallback.')
def time_offset(offset_settings): dir_offset = offset_settings['direction'] if (dir_offset not in [' ', '-', '+']): raise ValidationError('Time offset direction is not valid.') time_offset = offset_settings['time'] if (time_offset not in range(0,15)): raise ValidationError('Time offset amount is not valid.') if (dir_offset == ' ' and time_offset != 0): raise ValidationError('Direction cannot be empty if amount is not zero.') elif (dir_offset == '-' and time_offset in [13, 14]): raise ValidationError('Selected timezone is not valid.')
def domain_categories(categories, ruleset): if (ruleset == 'default' and not all(['malicious' in categories, 'cryptominer' in categories])): raise ValidationError('Malicious and cryptominer categories cannot be disabled.') dns_proxy = load_configuration('dns_proxy')['dns_proxy'] if (ruleset in ['default', 'user_defined']): cat_list = dns_proxy['categories'][ruleset] elif (ruleset in ['tlds']): cat_list = dns_proxy['tlds'] for category in categories: if category not in cat_list: raise ValidationError(INVALID_FORM)
def password(password): # calculating the length if (len(password) < 8): raise ValidationError('Password does not meet length requirement of 8 characters.') # searching for digits if (not re.search(r'\d', password) # searching for uppercase or not re.search(r'[A-Z]', password) # searching for lowercase or not re.search(r'[a-z]', password) # searching for symbols or not re.search(r'\W', password)): raise ValidationError('Password does not meet complexity requirements.')
def time_restriction(tr_settings): tr_hour = convert_int(tr_settings['hour']) tr_min = convert_int(tr_settings['minutes']) if (tr_hour not in range(1,13) or tr_min not in [00, 15, 30, 45]): raise ValidationError('Restriction settings are not valid.') tr_hour_len = convert_int(tr_settings['length_hour']) tr_min_len = convert_int(tr_settings['length_minutes']) if (tr_hour_len not in range(1,13) and tr_min_len not in [00, 15, 30, 45]): raise ValidationError('Restriction settings are not valid.') if (tr_settings['suffix'] not in ['AM', 'PM']): raise ValidationError('Restriction settings are not valid.')
def ip_proxy_settings(ip_hosts_settings, *, ruleset='categories'): ip_proxy = load_configuration('ip_proxy')['ip_proxy'] valid_categories = ip_proxy[ruleset] for category in ip_hosts_settings: try: category, direction = category[:-2], category[-1] except: raise ValidationError(INVALID_FORM) if (category not in valid_categories): raise ValidationError(INVALID_FORM) direction = convert_int(direction) if (direction not in range(4)): raise ValidationError(INVALID_FORM)
def add_snat_rule(nat_rule): # ensuring all necessary fields are present in the namespace before continuing. valid_fields = [ 'src_zone', 'orig_src_ip', 'new_src_ip', ] if not all([hasattr(nat_rule, x) for x in valid_fields]): raise ValidationError('Invalid form.')
def add_ip_whitelist(whitelist_ip, whitelist_settings): wl_user = whitelist_settings['user'] wl_type = whitelist_settings['type'] if (not wl_user.isalnum()): raise ValidationError( 'Standard fields can only contain alpha numeric characters.') if (wl_type not in ['global', 'tor']): raise ValidationError('Invalid form data.') dnx_settings = load_configuration('config')['settings'] local_net = IPv4Network(dnx_settings['local_net']['subnet']) ip_object = IPv4Address(whitelist_ip) if (ip_object not in local_net): raise ValidationError( 'IP Address must be inside of localnet. ex 192.168.83.10')
def standard(user_input, *, override=[]): for char in user_input: if (not char.isalnum() and char not in override): override = ', '.join(override) # TODO: F**K ENGLISH. MAKE THIS MAKE SENSE PLEASE GOD. F**K. raise ValidationError( f'Standard fields can only contain alpha numeric {override}.')
def del_firewall_rule(fw_rule): output = run( f'sudo iptables -nL {fw_rule.zone} --line-number', shell=True, capture_output=True ).stdout.splitlines() rule_count = len(output) + 2 if (convert_int(fw_rule.position) not in range(1, rule_count)): raise ValidationError('Selected rule is not valid and cannot be removed.')
def del_nat_rule(nat_rule): output = run( f'sudo iptables -t nat -nL {nat_rule.nat_type} --line-number', shell=True, capture_output=True ).stdout.splitlines()[1:] rule_count = len(output) if (convert_int(nat_rule.position) not in range(1, rule_count)): raise ValidationError('Selected rule is not valid and cannot be removed.')
def add_ip_whitelist(whitelist_settings): # handling alphanum check. will raise exception if invalid. standard(whitelist_settings['user']) if (whitelist_settings['type'] not in ['global', 'tor']): raise ValidationError(INVALID_FORM) # if ip is valid this will return, otherwise a ValidationError will be raised. _ip_address(whitelist_settings['user'])
def update_custom_category(category, *, action): with ConfigurationManager('dns_proxy') as dnx: custom_category_lists = dnx.load_configuration() ud_cats = custom_category_lists['dns_proxy']['categories']['user_defined'] if (action is CFG.DEL and category != 'enabled'): ud_cats.pop(category, None) elif (action is CFG.ADD): if (len(ud_cats) >= 6): raise ValidationError('Only support for maximum of 6 custom categories.') elif (category in ud_cats): raise ValidationError('Custom category already exists.') ud_cats[category] = {'enabled': False} dnx.write_configuration(custom_category_lists)
def license(user_input): user_input = user_input.lower() digits = set(string.digits) let_lower = set(string.ascii_lowercase) for letter in user_input: if (letter == '-'): continue if (letter not in digits and letter not in let_lower): raise ValidationError('Standard fields can only contain alpha numeric characters.')
def dhcp_reservation(reservation_settings): mac_address(reservation_settings['mac']) ip_address(reservation_settings['ip']) standard(reservation_settings['username']) dnx_settings = load_configuration('config')['settings'] local_net = IPv4Network(dnx_settings['local_net']['subnet']) ip_object = IPv4Address(reservation_settings['ip']) if (ip_object not in local_net): raise ValidationError('IP Address must be inside of localnet. ex 192.168.83.10')
def ip_address(ip_addr=None, *, ip_iter=None): ip_iter = [] if not ip_iter else ip_iter if (not isinstance(ip_iter, list)): return ValidationError('Data format must be a list.') if ip_addr: ip_iter.append(ip_addr) for ip in ip_iter: _ip_address(ip)
def add_dnat_rule(nat_rule): # ensuring all necessary fields are present in the namespace before continuing. valid_fields = ['src_zone', 'dst_port', 'host_ip', 'host_port', 'protocol'] if not all([hasattr(nat_rule, x) for x in valid_fields]): raise ValidationError('Invalid form.') if (nat_rule.protocol == 'icmp'): open_protocols = load_configuration('ips.json')['ips'] icmp_allow = open_protocols['open_protocols']['icmp'] if (icmp_allow): return 'Only one ICMP rule can be active at a time. Remove existing rule before adding another.'
def syslog_settings(syslog_settings): syslog = load_configuration('syslog_client')['syslog'] configured_syslog_servers = syslog['servers'] if (not configured_syslog_servers): raise ValidationError( 'Syslog servers must be configured before modifying client settings.' ) tls_retry = convert_int(syslog_settings['tls_retry']) tcp_retry = convert_int(syslog_settings['tcp_retry']) tls_settings = syslog_settings['tls'] syslog_settings = syslog_settings['syslog'] if (tls_retry not in [5, 10, 60] and tcp_retry not in [5, 10, 30]): raise ValidationError('Syslog settings are not valid.') for item in tls_settings: if (item not in [ 'enabled', 'tcp_fallback', 'udp_fallback', 'self_signed' ]): raise ValidationError('Syslog settings are not valid.') for item in syslog_settings: if (item not in ['syslog_enabled', 'syslog_protocol']): raise ValidationError('Syslog settings are not valid.') if ('syslog_protocol' not in syslog_settings): if ('encrypted_syslog' in tls_settings): raise ValidationError('TCP must be enabled to enable TLS.') if ('tcp_fallback' in tls_settings): raise ValidationError('TLS must be enabled before TCP fallback.')
def add_firewall_rule(firewall_rule): pos = convert_int(firewall_rule['pos']) protocol = firewall_rule['protocol'] dst_port = firewall_rule['dst_port'] output = run('sudo iptables -nL FIREWALL --line-number', shell=True, capture_output=True).stdout.splitlines() rule_count = len(output) - 1 if (rule_count == 1 and pos != 1): raise ValidationError('First firewall rule must have position 1.') else: if (pos not in range(1, rule_count)): raise ValidationError( f'Position outside of valid range. (1-{rule_count-1}') if (protocol not in ['any', 'tcp', 'udp', 'icmp']): raise ValidationError('Network protocol is not valid.') if (protocol in ['any', 'icmp'] and dst_port is not None): raise ValidationError('Only TCP/UDP use destination port field.')
def dhcp_reservation(reservation_settings): mac_address(reservation_settings['mac']) ip_address(reservation_settings['ip']) standard(reservation_settings['description'], override=[' ']) dhcp_settings = load_configuration('config')['settings'] reservation_ip = IPv4Address(reservation_settings['ip']) zone_net = IPv4Network(dhcp_settings['interfaces'][ reservation_settings['zone'].lower()]['subnet']) if (reservation_ip not in zone_net.hosts()): raise ValidationError( f'IP Address must fall within {str(zone_net)} range.')
def update_custom_category_domain(category, domain, reason=None, *, action): with ConfigurationManager('dns_proxy') as dnx: custom_category_domains = dnx.load_configuration() ud_cats = custom_category_domains['dns_proxy']['categories']['user_defined'] if (action is CFG.DEL and category != 'enabled'): ud_cats[category].pop(domain, None) elif (action is CFG.ADD): if (domain in ud_cats[category]): raise ValidationError('Domain rule already exists for this category.') else: ud_cats[category][domain] = reason dnx.write_configuration(custom_category_domains)
def del_firewall_rule(position, chain): if (chain == 'FIREWALL'): output = run('sudo iptables -nL FIREWALL --line-number', shell=True, capture_output=True).stdout.splitlines() elif (chain == 'NAT'): output = run('sudo iptables -t nat -nL NAT --line-number', shell=True, capture_output=True).stdout.splitlines() rule_count = len(output) - 1 position = convert_int(position) if (position not in range(1, rule_count)): raise ValidationError( 'Selected rule is not valid and cannot be removed.')
def configure_user_account(account_info, action): acct = SimpleNamespace(**account_info) with ConfigurationManager('logins') as dnx: accounts = dnx.load_configuration() userlist = accounts['users'] if (action is CFG.DEL): userlist.pop(acct.username) elif (action is CFG.ADD and acct.username not in userlist): Account = Authentication() hexpass = Account.hash_password(acct.username, acct.password) userlist.update( {acct.username: { 'password': hexpass, 'role': acct.role }}) else: raise ValidationError('User account already exists.') dnx.write_configuration(accounts)