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.' )
class Domain: 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}/data/dns_proxy.json', 'r') as categories: category = json.load(categories) self.valid = valid_commands['main']['configuration']['domain'] self.valid_domain = category['dns_proxy'] self.mod = 'domain' 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, _ = 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', 'enable', 'disable'} and not arg and not option): for arg, value in self.valid['settings'].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 elif (comm == 'show'): if (arg in self.valid_domain): self.ShowStatus(arg) else: self.Standard.SendNotice( f'invalid argument. use "show" command for all available options.' ) return elif (comm in {'enable', 'disable'} and arg_len == 2): self.ChangeStatus(comm, arg, option) 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 # all subsequent commands require length of 2 if (arg_len < 3): if (status and not option and comm in {'enable', 'disable'}): self.Standard.SendNotice( f'missing category. use "show categories" command for all available categories.' ) return if (comm in {'enable', 'disable'} and arg_len == 3): status = self.ValidateCategory(arg, option) if (status): self.ChangeStatus(comm, arg, option) def ShowStatus(self, arg): with open(f'{HOME_DIR}/data/dns_proxy.json', 'r') as settings: setting = json.load(settings) if (arg == 'keyword'): status = setting['dns_proxy']['keyword']['enabled'] if (status): status = 'ENABLED' else: status = 'DISABLED' keyword = self.Standard.CalculateSpace(arg) keyword_status = f'{keyword} {status}' self.conn.send(f'{keyword_status}\n'.encode('utf-8')) elif (arg in 'categories', 'tlds'): category = setting['dns_proxy'][arg] if (arg == 'categories'): category = category['default'] for cat, status in category.items(): if (status['enabled']): status = 'ENABLED' else: status = 'DISABLED' cat = self.Standard.CalculateSpace(cat) cat_status = f'{cat} {status}' self.conn.send(f'{cat_status}\n'.encode('utf-8')) def ChangeStatus(self, comm, arg, option): with open(f'{HOME_DIR}/data/dns_proxy.json', 'r') as settings: setting = json.load(settings) if (arg == 'keyword'): category = setting['dns_proxy']['keyword'] option = 'keyword' syntax = 'keyword' elif (arg == 'category'): category = setting['dns_proxy']['categories']['default'] if (option in {'malicious', 'cryptominer'} and comm == 'disable'): self.Standard.SendNotice( 'critical categories cannot be disabled.') return elif (arg == 'tld'): category = setting['dns_proxy']['tlds'] old_status = category[option]['enabled'] if (comm == 'enable'): category[option].update({'enabled': True}) elif (comm == 'disable'): category[option].update({'enabled': False}) new_status = category[option]['enabled'] if (old_status == new_status): if (arg == 'keyword'): self.Standard.SendNotice(f'{option} already {comm}d.') else: self.Standard.SendNotice(f'{arg} {option} already {comm}d.') else: syntax = self.valid['settings'][arg]['syntax'] with open(f'{HOME_DIR}/data/dns_proxy.json', 'w') as settings: json.dump(setting, settings, indent=4) self.Standard.SendNotice( f'{comm}d {option}. use "show {syntax}" command to check current status.' ) def ValidateCategory(self, arg, option): syntax = self.valid['settings'][arg]['syntax'] valid_domain = self.valid_domain[syntax] if (arg == 'category'): valid_domain = valid_domain['default'] if (option not in valid_domain): self.Standard.SendNotice( f'invalid {arg}. use "show {syntax}" to view all available {syntax}.' ) else: return True
class Whitelist: 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}/data/whitelist.json', 'r') as settings: setting = json.load(settings) self.valid = valid_commands['main']['configuration']['whitelist'] self.valid_whitelist = setting['whitelists'] self.mod = 'whitelist' 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 def Parse(self, data): arg_count = 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 == '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', 'add', 'delete'} and not arg): valid_args = self.valid['commands'][comm]['args'].strip('!') for arg, value in self.valid[valid_args].items(): if (comm == 'show' and arg in {'exception'}): arg = value['syntax'] info = value['info'] arg = self.Standard.CalculateSpace(arg) self.conn.send(f'{arg} {info}\n'.encode('utf-8')) 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 # commands length 2 if (arg_count < 2): return elif (comm == 'show'): self.ShowStatus(arg) return # commands length 3 if (arg_count < 3): if (status and not option): self.Standard.SendNotice(f'missing option after argument.') return # commands length 4 if (comm in {'add', 'delete'}): status = self.Standard.ValidateDomain(option) if (status and not option2): self.Standard.SendNotice( f'missing direction after argument. use "inbound", "outbound", or "both".' ) return if (status): if (arg == 'timebased'): status2 = self.Standard.ValidateListTimes(option2) elif (arg == 'exceptions'): status2 = self.Standard.AlphaNum(option2) if (status2): self.AddWhitelist(comm, arg, option, option2) def ShowStatus(self, arg): with open(f'{HOME_DIR}/data/whitelist.json', 'r') as settings: setting = json.load(settings) arg2 = arg if (arg == 'exceptions'): self.SendDescription('domain', 'reason') elif (arg == 'timebased'): arg = 'domains' self.SendDescription('domain', 'time entered', 'expire time') elif (arg == 'ip'): arg = 'ip_whitelist' self.SendDescription('ip address', 'type', 'user') whitelist = setting['whitelists'][arg] if (not whitelist): self.Standard.SendNotice(f'no {arg2} objects configured') return for whitelist, info in whitelist.items(): lists = self.Standard.CalculateSpace(whitelist) if (arg == 'exceptions'): info = info['reason'] elif (arg == 'domains'): time = info['time'] expire = info['expire'] info = self.Standard.FormatDateTime(time) info = self.Standard.CalculateSpace(info, space=12, symbol='| ', dashes=False) info += str(self.Standard.FormatDateTime(expire)) elif (arg == 'ip_whitelist'): user = info['user'] info = info['type'] info = self.Standard.CalculateSpace(info, space=10, symbol='| ', dashes=False) info += user wl_status = f'{lists} {info}' self.conn.send(f'{wl_status}\n'.encode('utf-8')) def AddWhitelist(self, comm, arg, option, option2): with open(f'{HOME_DIR}/data/whitelist.json', 'r') as settings: setting = json.load(settings) whitelist = setting['whitelists'] if (arg == 'exception'): if (option in whitelist['exceptions']): self.Standard.SendNotice(f'{option} is already whitelisted.') return else: whitelist['exceptions'].update({option: {'reason': option2}}) elif (option == 'timebased'): if (option in whitelist['domains']): self.Standard.SendNotice(f'{option} is already whitelisted.') return else: now = time.time() expire = now + (option2 * 60) whitelist['domains'].update({ option: { 'time': now, 'rule_length': option2 * 60, 'expire': expire } }) syntax = self.valid['settings'][arg]['syntax'] with open(f'{HOME_DIR}/data/whitelist.json', 'w') as settings: json.dump(setting, settings, indent=4) self.Standard.SendNotice( f'added {option}. use "show {syntax}" command to check current status.' ) def SendDescription(self, one, two, three=''): top = self.Standard.CalculateSpace(one, symbol=' ', dashes=False) top = top + ' ' + self.Standard.CalculateSpace( two, space=10, symbol=' ', dashes=False) + three self.conn.send(f'{top}\n'.encode('utf-8')) def ValidateCategory(self, arg, option): syntax = self.valid['settings'][arg]['syntax'] valid_whitelist = self.valid_whitelist[syntax] if (arg == 'category'): valid_whitelist = valid_whitelist['default'] if (option not in valid_whitelist): self.Standard.SendNotice( f'invalid {arg}. use "show {syntax}" to view all available {syntax}.' ) else: return True
class IP: 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/ip_proxy.json', 'r') as settings: setting = json.load(settings) self.valid = valid_commands['main']['configuration']['ip'] self.valid_ip = setting['ip_proxy'] self.mod = 'ip' 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 def Parse(self, 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 == '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'} and not arg): valid_args = self.valid['commands'][comm]['args'].strip('!') for arg, value in self.valid[valid_args].items(): if (comm == 'show' and arg in {'list', 'direction'}): arg = value['syntax'] info = value['info'] arg = self.Standard.CalculateSpace(arg) self.conn.send(f'{arg} {info}\n'.encode('utf-8')) return # all subsequent commands require length of 2 or 3 if (len(data) < 2): self.Standard.SendNotice(f'missing argument after command.') return elif (comm == 'show'): if (arg in self.valid_ip): self.ShowStatus(arg) else: self.Standard.SendNotice( f'invalid argument. use "show" command for all available options.' ) 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 # all subsequent commands require length of 2 if (len(data) < 3): if (status and not option): self.Standard.SendNotice( f'missing option after argument. use "show {arg}s" command for all available options.' ) return elif (comm in {'enable', 'disable'}): status = self.ValidateCategory(arg, option) if (status): self.ChangeStatus(comm, arg, option) # all subsequent require length 3 if (len(data) < 4): if (status and not option2): self.Standard.SendNotice( f'missing direction after argument. use "inbound", "outbound", or "both".' ) return elif (comm in {'set'}): status = self.ValidateDirection(option2) if (status): self.ChangeDirection(option, option2) return True def ShowStatus(self, arg): with open(f'{HOME_DIR}/dnx_system/data/ip_proxy.json', 'r') as settings: setting = json.load(settings) if (arg == 'lists'): category = setting['ip_proxy']['lists'] for cat, status in category.items(): if (cat == 'tor'): for node, status in category[cat].items(): if (status['enabled']): status = 'ENABLED' else: status = 'DISABLED' lists = self.Standard.CalculateSpace(f'tor_{node}') lists_status = f'{lists} {status}' self.conn.send(f'{lists_status}\n'.encode('utf-8')) continue elif (status['enabled']): status = 'ENABLED' else: status = 'DISABLED' lists = self.Standard.CalculateSpace(cat) lists_status = f'{lists} {status}' self.conn.send(f'{lists_status}\n'.encode('utf-8')) elif (arg == 'directions'): category = setting['ip_proxy']['directions'] for cat, status in category.items(): status = status.upper() cat = self.Standard.CalculateSpace(cat) cat_status = f'{cat} {status}' self.conn.send(f'{cat_status}\n'.encode('utf-8')) def ChangeStatus(self, comm, arg, option): with open(f'{HOME_DIR}/dnx_system/data/ip_proxy.json', 'r') as settings: setting = json.load(settings) if (option == {'tor_entry', 'tor_exit'}): category = setting['ip_proxy']['lists']['tor'] option = option.strip('tor_') elif (option == 'malware', 'compromised'): category = setting['ip_proxy']['lists'] old_status = category[option]['enabled'] if (comm == 'enable'): category[option].update({'enabled': True}) elif (comm == 'disable'): category[option].update({'enabled': False}) new_status = category[option]['enabled'] if (old_status == new_status): self.Standard.SendNotice(f'{arg} {option} already {comm}d.') else: syntax = self.valid['settings'][arg]['syntax'] with open(f'{HOME_DIR}/dnx_system/data/ip_proxy.json', 'w') as settings: json.dump(setting, settings, indent=4) self.Standard.SendNotice( f'{comm}d {option}. use "show {syntax}" command to check current status.' ) def ChangeDirection(self, option, option2): with open(f'{HOME_DIR}/dnx_system/data/ip_proxy.json', 'r') as settings: setting = json.load(settings) directions = setting['ip_proxy']['directions'] old_direction = directions[option] if (option2 == old_direction): self.Standard.SendNotice( f'{option} direction already set to {option2}.') else: directions.update({option: option2}) with open(f'{HOME_DIR}/dnx_system/data/ip_proxy.json', 'w') as settings: json.dump(setting, settings, indent=4) self.Standard.SendNotice( f'{option} direction set to {option2}. use "show directions" command to check current status.' ) def ValidateCategory(self, arg, option): syntax = self.valid['settings'][arg]['syntax'] valid_ip = self.valid_ip[syntax] if (arg == 'category'): valid_ip = valid_ip['default'] if (option not in valid_ip): self.Standard.SendNotice( f'invalid {arg}. use "show {syntax}" to view all available {syntax}.' ) else: return True def ValidateDirection(self, option2): if (option2 not in {'inbound', 'outbound', 'both'}): self.Standard.SendNotice( f'invalid direction. use "inbound", "outbound", or "both".') else: return True
class Services: 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']['services'] self.mod = 'services' 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 def Parse(self, data): comm, arg, _, _ = self.Standard.HandleArguments(data) if (comm not in self.valid['commands']): self.Standard.SendNotice( f'invalid command. type "commands" to view all available commands.' ) # single word commands if (comm == 'exit'): return 'EXIT' elif (comm == 'help'): self.Standard.ChangeHelpSetting() return elif (comm == 'status'): self.ShowStatus() elif (comm in {'show', 'start', 'restart', 'stop'} and not arg): valid_args = self.valid['commands'][comm]['args'].strip('!') for arg, value in self.valid[valid_args].items(): if (comm == 'show' and arg in {'exception'}): arg = value['syntax'] info = value['info'] arg = self.Standard.CalculateSpace(arg) self.conn.send(f'{arg} {info}\n'.encode('utf-8')) elif (comm in {'list', 'commands'}): if (comm == 'list'): comm = 'services' 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')) # all subsequent commands require length of 2 if (len(data) < 2): return # put invalid syntax here? args = self.Standard.GrabArgs(comm) status = self.Standard.ValidateArgs(arg, args) if (not status): self.Standard.SendNotice(f'invalid service. ex. {comm} dns-proxy') return if (comm in self.valid['commands']): if (status): self.ChangeStatus(comm, arg) def ChangeStatus(self, comm, service): # run(f'sudo systemctl {comm} {service}', shell=True) time.sleep(.5) action = self.valid['commands'][comm]['syntax'] self.Standard.SendNotice( f'{action} {service}. use "status" command to check current status' ) def ShowStatus(self): all_status = [] for service in self.valid['services']: try: service_status = run(f'sudo systemctl status dnx-{service}', shell=True, stdout=PIPE) service_status.check_returncode() status = '[+] UP' except CalledProcessError: status = '[-] DOWN' service = self.Standard.CalculateSpace(service) all_status.append(f'{service} {status}') for service_status in all_status: self.conn.send(f'{service_status}\n'.encode('utf-8'))