diff options
| author | root <root@krebs> | 2011-05-09 20:58:09 +0200 | 
|---|---|---|
| committer | root <root@krebs> | 2011-05-09 20:58:09 +0200 | 
| commit | 483a46be9a90ef46b3f478d62f108d675159cdc6 (patch) | |
| tree | a3a51b5a5bbd732e1972bd8b03f5bd9471571edd /modules | |
| parent | 56cbb651fa8d5fd6c467b37da4faf745e625ce6c (diff) | |
changed repos directory to fit krebs
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/people/README.md | 14 | ||||
| -rw-r--r-- | modules/people/TODO.md | 4 | ||||
| -rw-r--r-- | modules/people/VERSION | 1 | ||||
| -rwxr-xr-x | modules/people/bin/run.sh | 5 | ||||
| -rw-r--r-- | modules/people/conf/example.json | 22 | ||||
| -rw-r--r-- | modules/people/src/arping.py | 30 | ||||
| -rwxr-xr-x | modules/people/src/main.py | 33 | ||||
| -rwxr-xr-x | modules/people/src/snmp_users.py | 122 | 
8 files changed, 231 insertions, 0 deletions
diff --git a/modules/people/README.md b/modules/people/README.md new file mode 100644 index 00000000..d28100d3 --- /dev/null +++ b/modules/people/README.md @@ -0,0 +1,14 @@ +SNMP Users +========== + +asks an snmp-router for its arp-list and tries to verify this list via +ARPING. The snmping is done via snmp-net and command line parsing, +the arping uses 'scapy'. + +This script needs superuser rights and otherwise will just skip the +verification + +SNMPWALK Command +=============== + +snmpwalk -c shammunity 10.42.0.1 1.3.6.1.2.1.3.1.1.2 diff --git a/modules/people/TODO.md b/modules/people/TODO.md new file mode 100644 index 00000000..dfefa9a0 --- /dev/null +++ b/modules/people/TODO.md @@ -0,0 +1,4 @@ +BUGS +===== +- an exception is thrown but handled wrong when snmp servers and arping is +  unreachable diff --git a/modules/people/VERSION b/modules/people/VERSION new file mode 100644 index 00000000..6c50e659 --- /dev/null +++ b/modules/people/VERSION @@ -0,0 +1 @@ ++++++++[>+++++++>+++++++<<-]>.>---.<-. diff --git a/modules/people/bin/run.sh b/modules/people/bin/run.sh new file mode 100755 index 00000000..6da3d059 --- /dev/null +++ b/modules/people/bin/run.sh @@ -0,0 +1,5 @@ +#!/bin/bash +echo basedir $0 +BINDIR="`dirname $0`/../src" + +python2 "$BINDIR/main.py" $@ diff --git a/modules/people/conf/example.json b/modules/people/conf/example.json new file mode 100644 index 00000000..f34c20f0 --- /dev/null +++ b/modules/people/conf/example.json @@ -0,0 +1,22 @@ +{ +  "snmp_users": { +    "amqp": { +      "connection": { +        "login": "guest", +        "password": "guest", +        "host": "localhost" +      }, +      "out": { +        "exchange": "snmp_src" +      } +    }, +    "snmp": { +      "server": "127.0.0.1", +      "community": "community" +    }, +    "arping": { +      "active": true, +      "dev": "eth0" +    } +  } +} diff --git a/modules/people/src/arping.py b/modules/people/src/arping.py new file mode 100644 index 00000000..11fb81a9 --- /dev/null +++ b/modules/people/src/arping.py @@ -0,0 +1,30 @@ +#!/usr/bin/python2 + +import logging  +log = logging.getLogger('arpingy') +import os +try: +  if (os.geteuid() != 0): +    raise Exception('no root permissions') +  from scapy.all import * #might throws "no such module" + +  def arpingy(iprange="10.42.1.0/24",iface='eth0'): +    log.debug("pinging "+ str(iprange)) +    """Arping function takes IP Address or Network, returns nested mac/ip list""" +    try: +      conf.verb=0 +      ans,unans=arping(iprange,iface=iface,timeout=1) + +      collection = [] +      for snd, rcv in ans: +        result = rcv.sprintf(r"%ARP.psrc% %Ether.src%").split() +        log.debug(result) +        return result # take just the first arp reply +    except Exception as e: +      print ("something went wrong while arpinging " + str(e)) +    return [] + +except Exception as e: +  log.error("Cannot load arping functions!" + str(e)) +  def arpingy(iprange='',iface=''): +    raise Exception ('arping not available') diff --git a/modules/people/src/main.py b/modules/people/src/main.py new file mode 100755 index 00000000..c70bffd4 --- /dev/null +++ b/modules/people/src/main.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python2 +import sys,json,time +from snmp_users import snmp_users +import logging +import genericore as gen +MODULE_NAME='snmp_users' +log = logging.getLogger(MODULE_NAME) +PROTO_VERSION = 1 +DESCRIPTION = 'performes statistical analysis against mails from stream' + + +# set up instances of needed modules +conf = gen.Configurator(PROTO_VERSION,DESCRIPTION)   +amqp = gen.auto_amqp(MODULE_NAME)    +s = snmp_users(MODULE_NAME)       # the magic mail parsing class + +conf.configure([amqp,s]) #set up parser and eval parsed stuff + +# start network connections +amqp.create_connection() + +log.info('Starting up snmp_users') +print ' Sending Messages in Intervals. To exit press CTRL+C' +try: +  while True: +    log.info("collecting data from network") +    ret = s.collect() +    data = { 'type' : 'snmp', 'subtype' : 0, 'data' : ret} +    log.debug("writing data to queue : %s" % data) +    amqp.publish(json.dumps(data)) +    time.sleep(s.repeat) +except Exception as e: +  print "something happened :( " + str(e) diff --git a/modules/people/src/snmp_users.py b/modules/people/src/snmp_users.py new file mode 100755 index 00000000..871ed9dd --- /dev/null +++ b/modules/people/src/snmp_users.py @@ -0,0 +1,122 @@ +#!/usr/bin/python2 + +import logging, subprocess,re +from multiprocessing import Pool +from genericore import Configurable +from arping import arpingy +log = logging.getLogger('snmp_users') + +DEFAULT_CONFIG= { +  "snmp" : { +      "server" : "127.0.0.1", +      "community" : "community", +      "tree" : "1.3.6.1.2.1.3.1.1.2" +    }, +  "arping" : { +    "active" : True, +    "dev" : "eth0" +    } +} + +def arping_helper(dic): +  return arpingy(**dic) + +class snmp_users(Configurable): +  mac_list = {} + +  def __init__(self,MODULE_NAME,config=None): +    self.NAME=MODULE_NAME +    newConf = { MODULE_NAME : DEFAULT_CONFIG } +    Configurable.__init__(self,newConf) +    self.load_conf(config) + +  def call_external(self): +    """returns an array of lines produced by snmpwalk """ +    conf = self.config[self.NAME]['snmp'] + +    out = subprocess.Popen( +        ['snmpwalk', +          '-v2c', +          '-c',conf['community'], +          conf['server'], +          conf['tree']], +        stdout=subprocess.PIPE).communicate()[0] +    return out.split('\n') + +  def parse_output(self,output): +    """ parses output lines produced by snmpwalk """ +    data = [] +    for i in output:  +      if i == '': +        continue +      data.append(re.sub(r'.*\.(\d+\.\d+\.\d+\.\d+) = Hex-STRING: ([ 0-9A-F]*) ', r'\1 : \2',i).split(' : ')) +    data = [ [ip,':'.join(mac.split()).lower()] for ip,mac in data] #sanitize + +    return data + +  def update_results(self,new): +    """ Verifies ip and mac via ARP Scan  +        in addition it adds the correct ip to the mac_list """  +    macl = self.mac_list = {} +    for ip,mac in new: # fill the mac_list +      if not macl.get(mac,None): +        macl[mac] = [] +      macl[mac].append(ip) +    return True + +  def verify(self,snmp_data): +    """ verifies retrieved data where data is an array of arrays where +    [0] is the ip and [1] is the mac (space-delimited)""" +    arp_data = self.arping_parallel(snmp_data) +    self.update_results(arp_data) + +  def get_own_addr(self): +    data = subprocess.Popen(['/sbin/ifconfig',self.config[self.NAME]['arping']['dev']], +        stdout=subprocess.PIPE).communicate()[0].replace('\n','') +    return re.sub(r'.*HWaddr ([0-9:A-F]*).*inet addr:([0-9.]*).*' ,r'\1 \2',data).split() + + +  def arping_parallel(self,data): +    conf = self.config[self.NAME]['arping'] +    if conf['active']: +      tmp = [ {'iprange':dat[0],'iface':conf['dev']} for dat in data] +      try: +        p = Pool(10) +        ret = filter(lambda x:x , p.map(arping_helper, tmp)) + +        myip,mymac = self.get_own_addr() #append self to list +        ret.append([mymac,myip ] ) +        p.terminate() +        return ret +      except Exception as e: +        log.warning("Something happened,falling back to original data: "+ str(e)) +        return data + +  def collect(self): +    output = self.call_external() +    data = self.parse_output(output) +    if not data: +      raise Exception('External tool had not returned any parsable output') +    log.debug('Got following output from snmpwalk program: ' +str(data)) +    macs = self.verify(data) +    #self.print_results(self.mac_list) +    return self.mac_list + +  def print_results(self,macs): +    log.debug('printing results:') +    print '\n'.join([ mac + " => %s" % +      str(ips) for mac,ips in macs.items() ]) +    print '%d *unique* nodes in network' % len(macs) + +  def populate_parser(self,parser): +    parser.add_argument('--repeat',type=int,dest='repeat',default=30,help='Seconds between Scans',metavar='SECS') #TODO add this to configuration + +  def eval_parser(self,parsed): +    self.repeat = parsed.repeat + +if __name__ == "__main__": +  logging.basicConfig(level=logging.INFO) +  a = snmp_users() +  print a.get_own_addr() +  a.collect() +  a.print_results(a.mac_list)  | 
