class IPS: def __init__(self, Main): self.Main = Main self.conn = Main.conn with open(f'{HOME_DIR}/dnx_shell/commands.json', 'r') as commands: valid_commands = json.load(commands) self.valid = valid_commands['main']['configuration']['ips'] self.mod = 'ips-ids' self.Standard = Standard(self) def CommandLoop(self): while True: self.conn.send(f'dnx|{self.mod}$> '.encode('utf-8')) data = self.conn.recv(1024).decode().strip('\r\n') data = data.lower().split() if not data: continue status = self.Parse(data) if (status == 'EXIT'): break elif (status == 'end'): return 'exit' def Parse(self, data): arg_len = len(data) comm, arg, option, option2 = self.Standard.HandleArguments(data) if (comm is None): return elif (comm not in self.valid['commands']): self.Standard.SendNotice( f'invalid command. type "commands" to view all available commands.' ) return # single word commands if (comm == 'exit'): return 'EXIT' elif (comm == 'end'): return 'END' elif (comm == 'help'): self.Standard.ChangeHelpSetting() return elif (comm == 'commands'): for cm, values in self.valid[comm].items(): info = values['info'] cm = self.Standard.CalculateSpace(cm) self.conn.send(f'{cm} {info}\n'.encode('utf-8')) return elif (comm in {'show', 'set', 'enable', 'disable'} and not arg and not option): arg_list = self.valid['commands'][comm]['args'].strip('!') for arg, value in self.valid[arg_list].items(): if (comm == 'show' and arg in {'category', 'tld'}): arg = value['syntax'] info = value['info'] arg = self.Standard.CalculateSpace(arg) self.conn.send(f'{arg} {info}\n'.encode('utf-8')) return # commands length 2 if (arg_len < 2): return args = self.Standard.GrabArgs(comm) status = self.Standard.ValidateArgs(arg, args) if (not status): self.Standard.SendNotice( f'invalid argument. use "{comm}" command for all available options.' ) return elif (comm == 'show'): self.ShowStatus(arg) return # all subsequent commands require length of 2 if (arg_len < 3): if (status and not option): arg_list = self.valid['commands'][comm]['args'].strip('!') arg_options = self.valid[arg_list][arg]['options'] for option in arg_options: arg2 = self.Standard.CalculateSpace(arg) self.conn.send(f'{arg2} {option}\n'.encode('utf-8')) return if (comm in {'enable', 'disable'} and arg_len == 3): status = self.ValidateEnDisSetting(arg, option) if (status): self.ChangeStatus(comm, arg, option) if (arg_len < 4): if (status and not option2): if (arg == 'ddos' and option in {'tcp', 'udp', 'icmp'}): option = self.Standard.CalculateSpace(option) ddos_option = f'{option} *10-99*' self.conn.send(f'{ddos_option}\n'.encode('utf-8')) elif (arg == 'portscan' and option in {'block-length'}): option = self.Standard.CalculateSpace(option) for val in [0, 24, 48, 72]: portscan_option = f'{option} {val}' self.conn.send(f'{portscan_option}\n'.encode('utf-8')) elif (arg == 'whitelist'): option = self.Standard.CalculateSpace(option) whitelist_option = f'{option} *reason*' self.conn.send(f'{whitelist_option}\n'.encode('utf-8')) return elif (comm == 'set'): status = self.ValidateOptions(arg, option, option2) if (status): self.ConfigureOption(arg, option, option2) def ShowStatus(self, arg): with open(f'{HOME_DIR}/dnx_system/data/ips.json', 'r') as settings: setting = json.load(settings) if (arg == 'whitelist'): dns_servers = setting['ips']['whitelist']['dns_servers'] if (dns_servers): status = 'ENABLED' else: status = 'DISABLED' dns_servers = self.Standard.CalculateSpace(arg) dns_servers_status = f'{dns_servers} {status}' self.conn.send(f'{dns_servers_status}\n'.encode('utf-8')) user_whitelist = setting['ips']['whitelist']['ip_whitelist'] for ip_address, reason in user_whitelist.items(): ip_address = self.Standard.CalculateSpace(ip_address) ip_address_whitelist = f'{ip_address} {reason}' self.conn.send(f'{ip_address_whitelist}\n'.encode('utf-8')) elif (arg in 'portscan'): portscan_settings = setting['ips']['port_scan'] for setting, status in portscan_settings.items(): if (setting != 'length'): if (status): status = 'ENABLED' else: status = 'DISABLED' else: status = f'{status} hours' setting = self.Standard.CalculateSpace(setting) setting_status = f'{setting} {status}' self.conn.send(f'{setting_status}\n'.encode('utf-8')) if (arg == 'ddos'): status = setting['ips']['ddos']['enabled'] if (status): status = 'ENABLED' else: status = 'DISABLED' prevention = self.Standard.CalculateSpace('prevention') prevention_status = f'{prevention} {status}' self.conn.send(f'{prevention_status}\n'.encode('utf-8')) limits = setting['ips']['ddos']['limits'] for direction, settings in limits.items(): self.conn.send(f' {direction}\n'.encode('utf-8')) for protocol, pps in settings.items(): protocol = self.Standard.CalculateSpace(protocol) protocol_pps = f'{protocol} {pps} pps' self.conn.send(f'{protocol_pps}\n'.encode('utf-8')) def ChangeStatus(self, comm, arg, option): with open(f'{HOME_DIR}/dnx_system/data/ips.json', 'r') as settings: setting = json.load(settings) if (arg == 'portscan'): category = setting['ips']['port_scan'] elif (arg == 'ddos'): category = setting['ips']['ddos'] option = 'enabled' elif (arg == 'whitelist'): category = setting['ips']['whitelist'] option = 'dns_servers' old_status = category[option] if (comm == 'enable'): category.update({option: True}) elif (comm == 'disable'): category.update({option: False}) new_status = category[option] if (old_status == new_status): self.Standard.SendNotice(f'{arg} {option} already {comm}d.') else: with open(f'{HOME_DIR}/dnx_system/data/ips.json', 'w') as settings: json.dump(setting, settings, indent=4) self.Standard.SendNotice( f'{comm}d {arg} {option}. use "show {arg}" command to check current status.' ) def ConfigureOption(self, arg, option, option2): with open(f'{HOME_DIR}/dnx_system/data/ips.json', 'r') as settings: setting = json.load(settings) option_setting = setting[arg] if (arg in {'portscan', 'ddos'}): if (arg == 'portscan'): option2 = 'length' old_status = option_setting[option][option2] option_setting.update({option: option2}) new_status = option_setting[option][option2] if (old_status == new_status): self.Standard.SendNotice( f'{arg} {option} already set to {option2}.') else: with open(f'{HOME_DIR}/dnx_system/data/ips.json', 'w') as settings: json.dump(setting, settings, indent=4) self.Standard.SendNotice( f'{arg} {option} set to {option2}. use "show {arg}" command to check current status.' ) def ValidateEnDisSetting(self, arg, option): if (arg == 'portscan'): if (option in {'prevention', 'reject'}): return True elif (arg == 'ddos'): if (option in {'prevention'}): return True elif (arg == 'whitelist'): if (option in {'dns'}): return True self.Standard.SendNotice( f'invalid {arg} setting. use "show {arg}" to view all available settings.' ) def ValidateOptions(self, arg, option, option2): if (arg == 'ddos'): if (option in {'tcp', 'udp', 'icmp'}): if (option2.isdigit() and int(option2) in range(10, 100)): return True else: message = f'invalid packet per second. use "set ddos {option}" command for available options.' else: message = f'invalid protocol. use "set ddos" command for available options.' elif (arg == 'portscan'): if (option in {'block-length'}): if (option2.isdigit() and int(option2) in {0, 24, 48, 72}): return True else: message = 'invalid block length. use "set portscan block-length" command for available options.' else: message = 'invalid option. use "set portscan" command for available options.' def ValidateADDorDelete(self): if (arg == 'whitelist'): valid_ip = self.Standard.ValidateIP(option) if (valid_ip): valid_string = self.Standard.AlphaNum(option2) if (valid_string): return True else: message = 'invalid reason. must be alpha numeric characters.' else: message = 'invalid ip address.' self.Standard.SendNotice(message)
class Interface: def __init__(self, Main): self.Main = Main self.conn = Main.conn with open(f'{HOME_DIR}/dnx_shell/commands.json', 'r') as commands: valid_commands = json.load(commands) self.valid = valid_commands['main']['configuration']['interface'] # self.valid_interface = category['dns_server'] self.mod = 'interfaces' self.interface_settings_pending = { 'ip_address': { 'setting': None, 'syntax': 'ip-address' }, 'netmask': { 'setting': None, 'syntax': 'netmask' }, 'default_gateway': { 'setting': None, 'syntax': 'default-gateway' }, 'mac_address': { 'setting': None, 'syntax': 'mac-address' }, 'mode': { 'setting': None, 'syntax': 'mode' } } self.Standard = Standard(self) self.ShowIPAddress(initial_load=True) def CommandLoop(self): while True: self.conn.send(f'dnx|{self.mod}$> '.encode('utf-8')) data = self.conn.recv(1024).decode().strip('\r\n') data = data.lower().split() if not data: continue status = self.Parse(data) if (status == 'EXIT'): break elif (status == 'end'): return 'exit' def Parse(self, data): arg_len = len(data) comm, arg, option, option2 = self.Standard.HandleArguments(data) if (comm is None): return # print(f'MODULE: {self.Main.help_messages}') if (comm not in self.valid['commands']): self.Standard.SendNotice( f'invalid command. type "commands" to view all available commands.' ) return # single word commands if (comm == 'exit'): return 'EXIT' elif (comm == 'end'): return 'END' elif (comm == 'help'): self.Standard.ChangeHelpSetting() return elif (comm == 'configure'): self.ApplyPending() elif (comm == 'commands'): for cm, values in self.valid[comm].items(): info = values['info'] cm = self.Standard.CalculateSpace(cm) self.conn.send(f'{cm} {info}\n'.encode('utf-8')) return elif (comm in {'show'} and not arg): valid_args = self.valid['commands'][comm]['args'].strip('!') for arg, value in self.valid['settings'].items(): info = value['info'] arg = self.Standard.CalculateSpace(arg) self.conn.send(f'{arg} {info}\n'.encode('utf-8')) elif (comm in {'set'} and not arg): valid_args = self.valid['commands'][comm]['args'].strip('!') for arg, value in self.valid[valid_args].items(): info = value['info'] arg = self.Standard.CalculateSpace(arg) self.conn.send(f'{arg} {info}\n'.encode('utf-8')) return # commands length 2 if (arg_len < 2): return args = self.Standard.GrabArgs(comm) status = self.Standard.ValidateArgs(arg, args) if (not status): self.Standard.SendNotice( f'invalid argument. use "{comm}" command for all available arguments.' ) return elif (comm == 'show'): if (arg in {'ip-address'}): self.ShowIPAddress() elif (arg in {'mac-address'}): self.ShowMACAddress() elif (arg in {'pending'}): self.ShowPending() return elif (comm in {'enable', 'disable'}): self.ChangeStatus(comm, arg, option) return # command length 3 if (arg_len < 3): if (status and not option): arg_list = self.valid['commands'][comm]['args'].strip('!') arg_options = self.valid[arg_list][arg]['options'] for option in arg_options: arg2 = self.Standard.CalculateSpace(arg) self.conn.send(f'{arg2} {option}\n'.encode('utf-8')) return # command length 4 if (comm in {'set'}): if (arg in {'mode'}): if (option not in {'dhcp', 'static'}): self.Standard.SendNotice( f'invalid interface mode. use static or dhcp.') else: self.InputSettings(arg, option) elif (arg in {'mac-address'}): status = self.Standard.ValidateMac(option) if (status): self.InputSettings(arg, option) elif (arg in {'netmask'}): status = self.Standard.ValidateNetmask(option) if (status): netmask = self.Standard.ConvertNetmask(option) self.InputSettings(arg, netmask) elif (arg in {'ip-address', 'default-gateway'}): status = self.Standard.ValidateIP(option) if (status and not option): self.Standard.SendNotice(f'missing ip address.') elif (status and arg in {'ip-address'}): self.InputSettings(arg, option) elif (status and arg in {'default-gateway'}): ip_address, netmask = self.CheckLoadedSettings() if (ip_address and netmask): status = self.Standard.ValidateDefaultGateway( option, ip_address, netmask) if (status): self.InputSettings(arg, option) def InputSettings(self, arg, option): arg = arg.replace('-', '_') if (option == 'none'): option = 'not set' self.interface_settings_pending[arg].update({'setting': option}) syntax = self.interface_settings_pending[arg].get('syntax') self.Standard.SendNotice( f'interface {syntax} pending change to {option}.') self.Standard.SendNotice( f'use "show pending" command to view set changes. use "configure" command to push pending settings.' ) def CheckLoadedSettings(self): if (self.interface_settings_pending['ip_address'].get('setting') and self.interface_settings_pending['netmask'].get('setting')): return ( self.interface_settings_pending['ip_address'].get('setting'), self.interface_settings_pending['netmask'].get('setting')) else: self.Standard.SendNotice( f'ip address and subnet mask must be configured before default gateway.' ) return (None, None) #checking all pending items to ensure the user is informed about how to properly apply the settings. will notify #the user if the current pending changes are not valid. def CheckInterfaceMode(self, notice=False): status = set() for setting, info in self.interface_settings_pending.items(): if (setting in {'mac_address', 'mode'}): continue if (info['setting']): status.add(True) #will check mode when applying settings or when using show pending command. the notice flags will be set #if the method is called from the show pending method otherwise it will not be set. if (self.interface_settings_pending['mode'].get('setting') != 'static' and status): if (not notice): self.Standard.SendNotice( f'interface mode must be set to static before applying pending settings.' ) else: self.Standard.SendNotice( f'note: interface mode must be set to static prior to applying any ip related settings.' ) else: return True def ShowPending(self): for info in self.interface_settings_pending.values(): pending_name = info['syntax'] pending_setting = info['setting'] if (not pending_setting): pending_setting = 'not set' self.Standard.ShowSend(pending_name, pending_setting) self.CheckInterfaceMode(notice=True) def ShowIPAddress(self, initial_load=False): Inter = Int() with open(f'{HOME_DIR}/data/config.json', 'r') as settings: setting = json.load(settings) interface_settings = setting['settings']['interface'] default_wan_mac = interface_settings['wan']['default_mac'] configured_wan_mac = interface_settings['wan']['configured_mac'] dhcp = interface_settings['wan']['dhcp'] wan_int = interface_settings['outside'] if (not configured_wan_mac): configured_wan_mac = default_wan_mac if (dhcp): wan_mode = 'dhcp' else: wan_mode = 'static' wan_ip = Inter.IP(wan_int) wan_netmask = Inter.Netmask(wan_int) wan_dfg = Inter.DefaultGateway(wan_int) if (initial_load): self.interface_settings_pending['mode'].update( {'setting': wan_mode}) else: self.Standard.ShowSend('ip-address', wan_ip) self.Standard.ShowSend('netmask', wan_netmask) self.Standard.ShowSend('default-gateway', wan_dfg) self.Standard.ShowSend('mode', wan_mode) def ShowMACAddress(self): with open(f'{HOME_DIR}/data/config.json', 'r') as settings: setting = json.load(settings) interface_settings = setting['settings']['interface'] default_wan_mac = interface_settings['wan']['default_mac'] configured_wan_mac = interface_settings['wan']['configured_mac'] if (not configured_wan_mac): configured_wan_mac = default_wan_mac self.Standard.ShowSend('mac-address', configured_wan_mac) def ChangeMode(self, comm, arg, option): self.interface_settings_pending['mode'].update({'setting': option}) self.Standard.SendNotice( f'interface mode set to {option}. use "show pending" command to check loaded configuration.' ) def ChangeStatus(self, comm, arg, option): with open(f'{HOME_DIR}/data/dns_server.json', 'r') as settings: setting = json.load(settings) if (comm == 'set' and arg == 'tls-retry'): tls = setting['dns_server']['tls'] retry_amount = int(option) * 60 if (tls['retry'] == retry_amount): self.Standard.SendNotice( f'tls-retry is already set to {option} minutes.') else: tls.update({'retry': retry_amount}) with open(f'{HOME_DIR}/data/dns_server.json', 'w') as settings: json.dump(setting, settings, indent=4) self.Standard.SendNotice( f'set {arg} to {option} minutes. use "show tls-retry" command to check current status.' ) return tls_settings = setting['dns_server']['tls'] if (arg == 'udp-fallback'): arg2 = 'fallback' else: arg2 = 'enabled' old_status = tls_settings[arg2] if (comm == 'enable'): tls_settings.update({arg2: True}) elif (comm == 'disable'): tls_settings.update({arg2: False}) new_status = tls_settings[arg2] if (old_status == new_status): self.Standard.SendNotice(f'{arg} already {comm}d.') else: with open(f'{HOME_DIR}/data/dns_server.json', 'w') as settings: json.dump(setting, settings, indent=4) self.Standard.SendNotice( f'{comm}d {arg}. use "show {arg2}" command to check current status.' ) def ConfigureNetmask(self, netmask): self.interface_settings_pending['netmask'].update({'setting': netmask}) self.Standard.SendNotice( f'netmask set to {netmask}. use "show pending" command to check loaded configuration.' ) def ApplyPending(self): if (self.interface_settings_pending == 'dhcp'): for setting, info in self.interface_settings_pending.items(): if (setting in {'mac_address', 'mode'}): continue if (info['setting']): pass
class DNS: def __init__(self, Main): self.Main = Main self.conn = Main.conn with open(f'{HOME_DIR}/dnx_shell/commands.json', 'r') as commands: valid_commands = json.load(commands) with open(f'{HOME_DIR}/dnx_system/data/dns_server.json', 'r') as categories: category = json.load(categories) self.valid = valid_commands['main']['configuration']['dns'] self.valid_dns = category['dns_server'] self.mod = 'dns' self.Standard = Standard(self) def CommandLoop(self): while True: self.conn.send(f'dnx|{self.mod}$> '.encode('utf-8')) data = self.conn.recv(1024).decode().strip('\r\n') data = data.lower().split() if not data: continue status = self.Parse(data) if (status == 'EXIT'): break elif (status == 'end'): return 'exit' def Parse(self, data): arg_len = len(data) comm, arg, option, option2 = self.Standard.HandleArguments(data) if (comm not in self.valid['commands']): self.Standard.SendNotice( f'invalid command. type "commands" to view all available commands.' ) return # single word commands if (comm == 'exit'): return 'EXIT' elif (comm == 'end'): return 'END' elif (comm == 'help'): self.Standard.ChangeHelpSetting() return elif (comm == 'commands'): for cm, values in self.valid[comm].items(): info = values['info'] cm = self.Standard.CalculateSpace(cm) self.conn.send(f'{cm} {info}\n'.encode('utf-8')) return elif (comm in {'show', 'set', 'clear', 'enable', 'disable'} and not arg and not option): valid_args = self.valid['commands'][comm]['args'].strip('!') for arg, value in self.valid[valid_args].items(): # if (comm == 'show' and arg in {'category', 'tld'}): # arg = value['syntax'] info = value['info'] arg = self.Standard.CalculateSpace(arg) self.conn.send(f'{arg} {info}\n'.encode('utf-8')) return # commands length 2 if (arg_len < 2): return args = self.Standard.GrabArgs(comm) status = self.Standard.ValidateArgs(arg, args) if (not status): self.Standard.SendNotice( f'invalid argument. use "{comm}" command for all available arguments.' ) return elif (comm == 'show'): valid_args = self.valid['commands'][comm]['args'].strip('!') if (arg in self.valid[valid_args]): self.ShowStatus(arg) else: self.Standard.SendNotice( f'invalid argument. use "show" command for all available options.' ) return elif (comm in {'enable', 'disable'}): self.ChangeStatus(comm, arg, option) return # command length 3 if (arg_len < 3): if (arg in {'server1', 'server2'} and not option): arg = 'servers' if (status and not option and arg in {'server1', 'server2'}): self.Standard.SendNotice( f'missing server ip address. use "show {arg}" command to view current servers.' ) return # command length 4 if (comm in {'set'}): if (arg in {'tls-retry'}): if (option not in {'5', '10', '60'}): self.Standard.SendNotice( f'invalid retry amount. use 5, 10, or 60.') else: self.ChangeStatus(comm, arg, option) elif (arg in {'server1', 'server2'}): status = self.Standard.ValidateIP(option) if (status and not option2): self.Standard.SendNotice( f'missing server name after ip address.') elif (status): status = self.Standard.AlphaNum(option2) if (status): self.ConfigureServer(arg, option, option2) def ShowStatus(self, arg): with open(f'{HOME_DIR}/dnx_system/data/dns_server.json', 'r') as settings: setting = json.load(settings) with open(f'{HOME_DIR}/dnx_system/data/dns_cache.json', 'r') as dns_cache: cache = json.load(dns_cache) if (arg == 'servers'): dns_servers = setting['dns_server']['resolvers'] for server_info in dns_servers.values(): name = server_info['name'] server = server_info['ip_address'] self.Standard.ShowSend(name, server) elif (arg == 'top-domains'): top_domains = cache['top_domains'] if (not top_domains): self.Standard.SendNotice(f'no top-domains currently cached') return for domain, pos in top_domains.items(): self.Standard.ShowSend(pos, domain) elif (arg in {'tls', 'udp-fallback'}): status = setting['dns_server']['tls']['enabled'] if (arg == 'udp-fallback'): status = setting['dns_server']['tls']['fallback'] if (status): status = 'ENABLED' else: status = 'DISABLED' self.Standard.ShowSend(arg, status) elif (arg == 'tls-retry'): arg_strip = arg.strip('tls-') retry_time = setting['dns_server']['tls'][arg_strip] retry_time /= 60 retry_time = f'{int(retry_time)} Minutes' self.Standard.ShowSend(arg, retry_time) def ChangeStatus(self, comm, arg, option): with open(f'{HOME_DIR}/dnx_system/data/dns_server.json', 'r') as settings: setting = json.load(settings) if (comm == 'set' and arg == 'tls-retry'): tls = setting['dns_server']['tls'] retry_amount = int(option) * 60 if (tls['retry'] == retry_amount): self.Standard.SendNotice( f'tls-retry is already set to {option} minutes.') else: tls.update({'retry': retry_amount}) with open(f'{HOME_DIR}/dnx_system/data/dns_server.json', 'w') as settings: json.dump(setting, settings, indent=4) self.Standard.SendNotice( f'set {arg} to {option} minutes. use "show tls-retry" command to check current status.' ) return tls_settings = setting['dns_server']['tls'] if (arg == 'udp-fallback'): arg2 = 'fallback' else: arg2 = 'enabled' old_status = tls_settings[arg2] if (comm == 'enable'): tls_settings.update({arg2: True}) elif (comm == 'disable'): tls_settings.update({arg2: False}) new_status = tls_settings[arg2] if (old_status == new_status): self.Standard.SendNotice(f'{arg} already {comm}d.') else: with open(f'{HOME_DIR}/dnx_system/data/dns_server.json', 'w') as settings: json.dump(setting, settings, indent=4) self.Standard.SendNotice( f'{comm}d {arg}. use "show {arg2}" command to check current status.' ) def ConfigureServer(self, arg, option, option2): with open(f'{HOME_DIR}/dnx_system/data/dns_server.json', 'r') as settings: setting = json.load(settings) dns_server = setting['dns_server']['resolvers'][arg] if (dns_server['ip_address'] == option): self.Standard.SendNotice(f'{arg} already configured to {option}.') else: dns_server.update({'name': option2, 'ip_address': option}) with open(f'{HOME_DIR}/dnx_system/data/dns_server.json', 'w') as settings: json.dump(setting, settings, indent=4) self.Standard.SendNotice( f'set {arg} to {option}. use "show servers" command to check current status.' )