def __init__(self, host, port, template, log_queue, mibpath): self.host = host self.port = port dom = etree.parse(template) mibs = dom.xpath('//conpot_template/snmp/mibs/*') #only enable snmp server if we have configuration items if not mibs: self.cmd_responder = None else: self.cmd_responder = CommandResponder(self.host, self.port, log_queue, mibpath) for mib in mibs: mib_name = mib.attrib['name'] for symbol in mib: symbol_name = symbol.attrib['name'] if 'instance' in symbol.attrib: # convert instance to integer-filled tuple symbol_instance = symbol.attrib['instance'].split('.') symbol_instance = tuple(map(int, symbol_instance)) else: # use default instance (0) symbol_instance = (0,) value = symbol.xpath('./value/text()')[0] self.cmd_responder.register(mib_name, symbol_name, symbol_instance, value)
def __init__(self, host, port, template, log_queue, mibpath): self.host = host self.port = port dom = etree.parse(template) mibs = dom.xpath('//conpot_template/snmp/mibs/*') #only enable snmp server if we have configuration items if not mibs: self.cmd_responder = None else: self.cmd_responder = CommandResponder(self.host, self.port, log_queue, mibpath) for mib in mibs: mib_name = mib.attrib['name'] for symbol in mib: symbol_name = symbol.attrib['name'] value = symbol.xpath('./value/text()')[0] self.cmd_responder.register(mib_name, symbol_name, value)
class SNMPServer(object): def __init__(self, host, port, template, log_queue, mibpath): self.host = host self.port = port dom = etree.parse(template) mibs = dom.xpath('//conpot_template/snmp/mibs/*') #only enable snmp server if we have configuration items if not mibs: self.cmd_responder = None else: self.cmd_responder = CommandResponder(self.host, self.port, log_queue, mibpath) for mib in mibs: mib_name = mib.attrib['name'] for symbol in mib: symbol_name = symbol.attrib['name'] value = symbol.xpath('./value/text()')[0] self.cmd_responder.register(mib_name, symbol_name, value) def start(self): if self.cmd_responder: logger.info('SNMP server started on: {0}'.format((self.host, self.port))) self.cmd_responder.serve_forever() def stop(self): if self.cmd_responder: self.cmd_responder.stop()
def __init__(self, host, port, template, log_queue, mibpaths, rawmibs_dirs): """ :param host: hostname or ip address on which to server the snmp service (string). :param port: listen port (integer). :param template: path to conpot xml configuration file (string). :param log_queue: shared log queue (list). :param mibpaths: collection of paths to search for COMPILED mib files (iterable collection of strings). :param rawmibs_dir: directory to search for raw mib files, these files will get compiled by conpot (string). """ self.host = host self.port = port dyn_rsp = DynamicResponder() dom = etree.parse(template) mibs = dom.xpath('//conpot_template/snmp/mibs/*') # only enable snmp server if we have configuration items if mibs: try: tmp_mib_dir = tempfile.mkdtemp() mibpaths.append(tmp_mib_dir) available_mibs = find_mibs(rawmibs_dirs) self.cmd_responder = CommandResponder(self.host, self.port, log_queue, mibpaths, dyn_rsp) # parse global snmp configuration snmp_config = dom.xpath('//conpot_template/snmp/config/*') if snmp_config: for entity in snmp_config: # TARPIT: individual response delays if entity.attrib['name'].lower() == 'tarpit': if entity.attrib['command'].lower() == 'get': self.cmd_responder.resp_app_get.tarpit = self.config_sanitize_tarpit(entity.text) elif entity.attrib['command'].lower() == 'set': self.cmd_responder.resp_app_set.tarpit = self.config_sanitize_tarpit(entity.text) elif entity.attrib['command'].lower() == 'next': self.cmd_responder.resp_app_next.tarpit = self.config_sanitize_tarpit(entity.text) elif entity.attrib['command'].lower() == 'bulk': self.cmd_responder.resp_app_bulk.tarpit = self.config_sanitize_tarpit(entity.text) # parse mibs and oid tables for mib in mibs: mib_name = mib.attrib['name'] # compile the mib file if it is found and not already loaded. if mib_name in available_mibs and not self.cmd_responder.has_mib(mib_name): compile_mib(mib_name, tmp_mib_dir) for symbol in mib: symbol_name = symbol.attrib['name'] # retrieve instance from template if 'instance' in symbol.attrib: # convert instance to (int-)tuple symbol_instance = symbol.attrib['instance'].split('.') symbol_instance = tuple(map(int, symbol_instance)) else: # use default instance (0) symbol_instance = (0,) # retrieve value from template value = symbol.xpath('./value/text()')[0] # retrieve engine from template if len(symbol.xpath('./engine')) > 0: engine_type = symbol.find('./engine').attrib['type'] engine_aux = symbol.findtext('./engine') else: # disable dynamic responses (static) engine_type = 'static' engine_aux = '' # register this MIB instance to the command responder self.cmd_responder.register(mib_name, symbol_name, symbol_instance, value, engine_type, engine_aux) finally: #cleanup compiled mib files shutil.rmtree(tmp_mib_dir) else: self.cmd_responder = None
class SNMPServer(object): def __init__(self, host, port, template, log_queue, mibpaths, rawmibs_dirs): """ :param host: hostname or ip address on which to server the snmp service (string). :param port: listen port (integer). :param template: path to conpot xml configuration file (string). :param log_queue: shared log queue (list). :param mibpaths: collection of paths to search for COMPILED mib files (iterable collection of strings). :param rawmibs_dir: directory to search for raw mib files, these files will get compiled by conpot (string). """ self.host = host self.port = port dyn_rsp = DynamicResponder() dom = etree.parse(template) mibs = dom.xpath('//conpot_template/snmp/mibs/*') # only enable snmp server if we have configuration items if mibs: try: tmp_mib_dir = tempfile.mkdtemp() mibpaths.append(tmp_mib_dir) available_mibs = find_mibs(rawmibs_dirs) self.cmd_responder = CommandResponder(self.host, self.port, log_queue, mibpaths, dyn_rsp) # parse global snmp configuration snmp_config = dom.xpath('//conpot_template/snmp/config/*') if snmp_config: for entity in snmp_config: # TARPIT: individual response delays if entity.attrib['name'].lower() == 'tarpit': if entity.attrib['command'].lower() == 'get': self.cmd_responder.resp_app_get.tarpit = self.config_sanitize_tarpit(entity.text) elif entity.attrib['command'].lower() == 'set': self.cmd_responder.resp_app_set.tarpit = self.config_sanitize_tarpit(entity.text) elif entity.attrib['command'].lower() == 'next': self.cmd_responder.resp_app_next.tarpit = self.config_sanitize_tarpit(entity.text) elif entity.attrib['command'].lower() == 'bulk': self.cmd_responder.resp_app_bulk.tarpit = self.config_sanitize_tarpit(entity.text) # parse mibs and oid tables for mib in mibs: mib_name = mib.attrib['name'] # compile the mib file if it is found and not already loaded. if mib_name in available_mibs and not self.cmd_responder.has_mib(mib_name): compile_mib(mib_name, tmp_mib_dir) for symbol in mib: symbol_name = symbol.attrib['name'] # retrieve instance from template if 'instance' in symbol.attrib: # convert instance to (int-)tuple symbol_instance = symbol.attrib['instance'].split('.') symbol_instance = tuple(map(int, symbol_instance)) else: # use default instance (0) symbol_instance = (0,) # retrieve value from template value = symbol.xpath('./value/text()')[0] # retrieve engine from template if len(symbol.xpath('./engine')) > 0: engine_type = symbol.find('./engine').attrib['type'] engine_aux = symbol.findtext('./engine') else: # disable dynamic responses (static) engine_type = 'static' engine_aux = '' # register this MIB instance to the command responder self.cmd_responder.register(mib_name, symbol_name, symbol_instance, value, engine_type, engine_aux) finally: #cleanup compiled mib files shutil.rmtree(tmp_mib_dir) else: self.cmd_responder = None def config_sanitize_tarpit(self, value): # checks tarpit value for being either a single int or float, # or a series of two concatenated integers and/or floats seperated by semicolon and returns # either the (sanitized) value or zero. if value is not None: x, _, y = value.partition(';') try: _ = float(x) except ValueError: logger.error("Invalid tarpit value: '{0}'. Assuming no latency.".format(value)) # first value is invalid, ignore the whole setting. return '0;0' try: _ = float(y) # both values are fine. return value except ValueError: # second value is invalid, use the first one. return x else: return '0;0' def start(self): if self.cmd_responder: logger.info('SNMP server started on: {0}'.format((self.host, self.port))) self.cmd_responder.serve_forever() def stop(self): if self.cmd_responder: self.cmd_responder.stop()
def __init__(self, host, port, template, log_queue, mibpaths, rawmibs_dirs): """ :param host: hostname or ip address on which to server the snmp service (string). :param port: listen port (integer). :param template: path to conpot xml configuration file (string). :param log_queue: shared log queue (list). :param mibpaths: collection of paths to search for COMPILED mib files (iterable collection of strings). :param rawmibs_dir: directory to search for raw mib files, these files will get compiled by conpot (string). """ self.host = host self.port = port dyn_rsp = DynamicResponder() dom = etree.parse(template) mibs = dom.xpath('//conpot_template/snmp/mibs/*') # only enable snmp server if we have configuration items if mibs: try: tmp_mib_dir = tempfile.mkdtemp() mibpaths.append(tmp_mib_dir) available_mibs = find_mibs(rawmibs_dirs) self.cmd_responder = CommandResponder(self.host, self.port, log_queue, mibpaths, dyn_rsp) # parse global snmp configuration snmp_config = dom.xpath('//conpot_template/snmp/config/*') if snmp_config: for entity in snmp_config: # TARPIT: individual response delays if entity.attrib['name'].lower() == 'tarpit': if entity.attrib['command'].lower() == 'get': self.cmd_responder.resp_app_get.tarpit = self.config_sanitize_tarpit( entity.text) elif entity.attrib['command'].lower() == 'set': self.cmd_responder.resp_app_set.tarpit = self.config_sanitize_tarpit( entity.text) elif entity.attrib['command'].lower() == 'next': self.cmd_responder.resp_app_next.tarpit = self.config_sanitize_tarpit( entity.text) elif entity.attrib['command'].lower() == 'bulk': self.cmd_responder.resp_app_bulk.tarpit = self.config_sanitize_tarpit( entity.text) # EVASION: response thresholds if entity.attrib['name'].lower() == 'evasion': if entity.attrib['command'].lower() == 'get': self.cmd_responder.resp_app_get.threshold = self.config_sanitize_threshold( entity.text) elif entity.attrib['command'].lower() == 'set': self.cmd_responder.resp_app_set.threshold = self.config_sanitize_threshold( entity.text) elif entity.attrib['command'].lower() == 'next': self.cmd_responder.resp_app_next.threshold = self.config_sanitize_threshold( entity.text) elif entity.attrib['command'].lower() == 'bulk': self.cmd_responder.resp_app_bulk.threshold = self.config_sanitize_threshold( entity.text) # parse mibs and oid tables for mib in mibs: mib_name = mib.attrib['name'] # compile the mib file if it is found and not already loaded. if mib_name in available_mibs and not self.cmd_responder.has_mib( mib_name): compile_mib(mib_name, tmp_mib_dir) for symbol in mib: symbol_name = symbol.attrib['name'] # retrieve instance from template if 'instance' in symbol.attrib: # convert instance to (int-)tuple symbol_instance = symbol.attrib['instance'].split( '.') symbol_instance = tuple(map(int, symbol_instance)) else: # use default instance (0) symbol_instance = (0, ) # retrieve value from template value = symbol.xpath('./value/text()')[0] # retrieve engine from template if len(symbol.xpath('./engine')) > 0: engine_type = symbol.find( './engine').attrib['type'] engine_aux = symbol.findtext('./engine') else: # disable dynamic responses (static) engine_type = 'static' engine_aux = '' # register this MIB instance to the command responder self.cmd_responder.register(mib_name, symbol_name, symbol_instance, value, engine_type, engine_aux) finally: #cleanup compiled mib files shutil.rmtree(tmp_mib_dir) else: self.cmd_responder = None
class SNMPServer(object): def __init__(self, host, port, template, log_queue, mibpaths, rawmibs_dirs): """ :param host: hostname or ip address on which to server the snmp service (string). :param port: listen port (integer). :param template: path to conpot xml configuration file (string). :param log_queue: shared log queue (list). :param mibpaths: collection of paths to search for COMPILED mib files (iterable collection of strings). :param rawmibs_dir: directory to search for raw mib files, these files will get compiled by conpot (string). """ self.host = host self.port = port dyn_rsp = DynamicResponder() dom = etree.parse(template) mibs = dom.xpath('//conpot_template/snmp/mibs/*') # only enable snmp server if we have configuration items if mibs: try: tmp_mib_dir = tempfile.mkdtemp() mibpaths.append(tmp_mib_dir) available_mibs = find_mibs(rawmibs_dirs) self.cmd_responder = CommandResponder(self.host, self.port, log_queue, mibpaths, dyn_rsp) # parse global snmp configuration snmp_config = dom.xpath('//conpot_template/snmp/config/*') if snmp_config: for entity in snmp_config: # TARPIT: individual response delays if entity.attrib['name'].lower() == 'tarpit': if entity.attrib['command'].lower() == 'get': self.cmd_responder.resp_app_get.tarpit = self.config_sanitize_tarpit( entity.text) elif entity.attrib['command'].lower() == 'set': self.cmd_responder.resp_app_set.tarpit = self.config_sanitize_tarpit( entity.text) elif entity.attrib['command'].lower() == 'next': self.cmd_responder.resp_app_next.tarpit = self.config_sanitize_tarpit( entity.text) elif entity.attrib['command'].lower() == 'bulk': self.cmd_responder.resp_app_bulk.tarpit = self.config_sanitize_tarpit( entity.text) # EVASION: response thresholds if entity.attrib['name'].lower() == 'evasion': if entity.attrib['command'].lower() == 'get': self.cmd_responder.resp_app_get.threshold = self.config_sanitize_threshold( entity.text) elif entity.attrib['command'].lower() == 'set': self.cmd_responder.resp_app_set.threshold = self.config_sanitize_threshold( entity.text) elif entity.attrib['command'].lower() == 'next': self.cmd_responder.resp_app_next.threshold = self.config_sanitize_threshold( entity.text) elif entity.attrib['command'].lower() == 'bulk': self.cmd_responder.resp_app_bulk.threshold = self.config_sanitize_threshold( entity.text) # parse mibs and oid tables for mib in mibs: mib_name = mib.attrib['name'] # compile the mib file if it is found and not already loaded. if mib_name in available_mibs and not self.cmd_responder.has_mib( mib_name): compile_mib(mib_name, tmp_mib_dir) for symbol in mib: symbol_name = symbol.attrib['name'] # retrieve instance from template if 'instance' in symbol.attrib: # convert instance to (int-)tuple symbol_instance = symbol.attrib['instance'].split( '.') symbol_instance = tuple(map(int, symbol_instance)) else: # use default instance (0) symbol_instance = (0, ) # retrieve value from template value = symbol.xpath('./value/text()')[0] # retrieve engine from template if len(symbol.xpath('./engine')) > 0: engine_type = symbol.find( './engine').attrib['type'] engine_aux = symbol.findtext('./engine') else: # disable dynamic responses (static) engine_type = 'static' engine_aux = '' # register this MIB instance to the command responder self.cmd_responder.register(mib_name, symbol_name, symbol_instance, value, engine_type, engine_aux) finally: #cleanup compiled mib files shutil.rmtree(tmp_mib_dir) else: self.cmd_responder = None def config_sanitize_tarpit(self, value): # checks tarpit value for being either a single int or float, # or a series of two concatenated integers and/or floats separated by semicolon and returns # either the (sanitized) value or zero. if value is not None: x, _, y = value.partition(';') try: _ = float(x) except ValueError: logger.error( "Invalid tarpit value: '{0}'. Assuming no latency.".format( value)) # first value is invalid, ignore the whole setting. return '0;0' try: _ = float(y) # both values are fine. return value except ValueError: # second value is invalid, use the first one. return x else: return '0;0' def config_sanitize_threshold(self, value): # checks DoS thresholds for being either a single int or a series of two concatenated integers # separated by semicolon and returns either the (sanitized) value or zero. if value is not None: x, _, y = value.partition(';') try: _ = int(x) except ValueError: logger.error( "Invalid evasion threshold: '{0}'. Assuming no DoS evasion." .format(value)) # first value is invalid, ignore the whole setting. return '0;0' try: _ = int(y) # both values are fine. return value except ValueError: # second value is invalid, use the first and ignore the second. return str(x) + ';0' else: return '0;0' def start(self): if self.cmd_responder: logger.info('SNMP server started on: {0}'.format( (self.host, self.port))) self.cmd_responder.serve_forever() def stop(self): if self.cmd_responder: self.cmd_responder.stop()