From 353dbba3c004a2dfbbbb42bfbc694783d3291716 Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Sun, 16 Jan 2011 07:38:58 +0100 Subject: Adds the arping script, as well as snmp-test added Readme and stuff, have a nice day. --- README.md | 14 ++++++++++ arping.py | 50 ++++++++++++++++++++++++++++++++++ main.py | 1 + snmp_users.py | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 README.md create mode 100644 arping.py create mode 100644 main.py create mode 100755 snmp_users.py diff --git a/README.md b/README.md new file mode 100644 index 00000000..d28100d3 --- /dev/null +++ b/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/arping.py b/arping.py new file mode 100644 index 00000000..60f271d2 --- /dev/null +++ b/arping.py @@ -0,0 +1,50 @@ +#!/usr/bin/python2 + +import logging +log = logging.getLogger('pingy') +import os +try: + if (os.geteuid() != 0): + raise Exception('no root permissions') + from scapy.all import * + + def arpingy(iprange="10.42.1.0/24",iface='eth0'): + log.debug("pinging"+ 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) + collection.append(result) + return collection + except Exception as e: + print ("something went wrong while arpinging " + str(e)) + return [] + + def pingy(ip="10.42.1.0/24",iface='eth0'): + log.debug("pinging"+ ip) + """Arping function takes IP Address or Network, returns nested mac/ip list""" + try: + conf.verb=0 + ans,unans=srp(Ether()/IP(dst=ip)/ICMP(),timeout=1) + + collection = [] + for snd, rcv in ans: + result = rcv.sprintf(r"%IP.src% %Ether.src%").split() + log.debug(result) + collection.append(result) + return collection + except Exception as e: + print ("something went wrong while arpinging " + str(e)) + return [] + +except Exception as e: + log.error("Cannot Arping!" + str(e)) + def pingy(iprange): + return True + def arpingy(iprange): + return True diff --git a/main.py b/main.py new file mode 100644 index 00000000..0e1d5dde --- /dev/null +++ b/main.py @@ -0,0 +1 @@ +#!/usr/bin/python2 diff --git a/snmp_users.py b/snmp_users.py new file mode 100755 index 00000000..df78cc8d --- /dev/null +++ b/snmp_users.py @@ -0,0 +1,87 @@ +#!/usr/bin/python2 +import subprocess,re +import logging +from arping import arpingy,pingy +log = logging.getLogger('snmp_users') + +class snmp_users: + mac_list = {} + + def __init__(self,server='10.42.0.1',community='shammunity'): + self.server = server + self.community = community + + def call_external(self): + """ creates a list of lines produced by snmpwal + """ + out = subprocess.Popen( + ['snmpwalk', + '-v2c', + '-c',self.community, + self.server, + '1.3.6.1.2.1.3.1.1.2'], + stdout=subprocess.PIPE).communicate()[0] + return out.split('\n') + + def parse_output(self,output): + """ parses output lines produced by snmpwalk""" + for i in output: + if i == '': + continue + + ip,mac = re.sub(r'.*\.(\d+\.\d+\.\d+\.\d+) = Hex-STRING: ([ 0-9A-F]*) ', + r'\1 : \2',i).split(' : ') + + verified = False + if self.verify_data(mac,ip,arpingy(ip)): + log.info("verfied by arping %s => %s" % (mac,ip)) + verified = True + + #elif self.verify_data(mac,ip,pingy(ip) ): builds up onto arp'ing... + # log.info("verfied by fallback ping %s => %s" % (mac,ip)) + # verfied = True + + if verified: + if mac in self.mac_list.keys(): + log.info( "%s already assigned for ip %s (new IP %s) " % + ( mac ,self.mac_list[mac], ip)) + self.mac_list[mac]['counter'] +=1 + continue + else: + log.debug("%s => %s" % (mac,ip)) + self.mac_list[mac] = { 'ip' : ip, 'counter' : 1} + else: + log.warning("Verification failed %s => %s" % (mac,ip)) + + def verify_data(self,mac,ip,ret): + """ Verifies ip and mac via ARP Scan """ + mac = ':'.join(mac.split()) + log.debug(ret) + + if type(ret) == type(True): + return True + elif ret != []: + ret = ret[0] + ret_mac = ret[1].upper() + if ret_mac == mac: + return True + else: + log.info('return mac not equal to expected, %s != %s' % (ret_mac,mac)) + else: + return False + + def collect(self): + output = self.call_external() + self.parse_output(output) + self.print_results() + def print_results(self): + print '\n'.join([ mac + " => " + ip['ip'] + " ( %d active leases )" % + ip['counter'] for mac,ip in self.mac_list.items() ]) + print '%d *unique* nodes in network' % len(self.mac_list) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + a = snmp_users() + a.collect() + -- cgit v1.2.3 From f95bf3d9f1c824f16205d29db24c5dcc0c5cb288 Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Mon, 17 Jan 2011 16:52:49 +0100 Subject: pingy thrown out --- arping.py | 25 +++---------------------- snmp_users.py | 2 +- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/arping.py b/arping.py index 60f271d2..ee96c9aa 100644 --- a/arping.py +++ b/arping.py @@ -1,12 +1,12 @@ #!/usr/bin/python2 import logging -log = logging.getLogger('pingy') +log = logging.getLogger('arpingy') import os try: if (os.geteuid() != 0): raise Exception('no root permissions') - from scapy.all import * + from scapy.all import * #might throws "no such module" def arpingy(iprange="10.42.1.0/24",iface='eth0'): log.debug("pinging"+ iprange) @@ -25,26 +25,7 @@ try: print ("something went wrong while arpinging " + str(e)) return [] - def pingy(ip="10.42.1.0/24",iface='eth0'): - log.debug("pinging"+ ip) - """Arping function takes IP Address or Network, returns nested mac/ip list""" - try: - conf.verb=0 - ans,unans=srp(Ether()/IP(dst=ip)/ICMP(),timeout=1) - - collection = [] - for snd, rcv in ans: - result = rcv.sprintf(r"%IP.src% %Ether.src%").split() - log.debug(result) - collection.append(result) - return collection - except Exception as e: - print ("something went wrong while arpinging " + str(e)) - return [] - except Exception as e: - log.error("Cannot Arping!" + str(e)) - def pingy(iprange): - return True + log.error("Cannot load arping functions!" + str(e)) def arpingy(iprange): return True diff --git a/snmp_users.py b/snmp_users.py index df78cc8d..481938d3 100755 --- a/snmp_users.py +++ b/snmp_users.py @@ -1,7 +1,7 @@ #!/usr/bin/python2 import subprocess,re import logging -from arping import arpingy,pingy +from arping import arpingy log = logging.getLogger('snmp_users') class snmp_users: -- cgit v1.2.3 From bcf8f6653e09d9b1072c6fbe87d03ae0257cba36 Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Mon, 17 Jan 2011 17:16:18 +0100 Subject: added main class for sending data to mq --- main.py | 38 +++++++++++++++++++++++++++++++++++++- snmp_users.py | 2 ++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index 0e1d5dde..868b5f7e 100644 --- a/main.py +++ b/main.py @@ -1 +1,37 @@ -#!/usr/bin/python2 +#!/usr/bin/env python2 +import pika +import json,argparse +from snmp_users import snmp_users +import logging +logging.basicConfig(level=logging.INFO) +log = logging.getLogger('snmp_exchange') + +SNMP_EXCHANGE='snmp_src' + +parser = argparse.ArgumentParser(description='generates dummy package on given exchange against AMQP') +parser.add_argument('--host',default='141.31.8.11', help='AMQP host ip address') +parser.add_argument('--port',type=int,default=5672, help='AMQP host port') +parser.add_argument('-u','--username',default='guest', help='AMQP username') +parser.add_argument('-p','--password',default='guest', help='AMQP password') +parser.add_argument('-r','--repeat',type=int,default=20, help='SNMP_Polling Delay') +args = parser.parse_args() + +connection = pika.AsyncoreConnection(pika.ConnectionParameters( + credentials = pika.PlainCredentials(args.username,args.password), + host=args.host,port=args.port)) +channel = connection.channel() + +channel.exchange_declare(exchange=SNMP_EXCHANGE, + type='fanout') + +log.info('Starting StatsForUser Module (mongodb)') +s = snmp_users() +print ' [*] Sending Messages in Intervals. To exit press CTRL+C' +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) + channel.basic_publish(exchange=SNMP_EXCHANGE, + routing_key='', + body=json.dumps(data)) diff --git a/snmp_users.py b/snmp_users.py index 481938d3..6eb5c33c 100755 --- a/snmp_users.py +++ b/snmp_users.py @@ -74,7 +74,9 @@ class snmp_users: output = self.call_external() self.parse_output(output) self.print_results() + return self.mac_list def print_results(self): + log.debug('printing results:') print '\n'.join([ mac + " => " + ip['ip'] + " ( %d active leases )" % ip['counter'] for mac,ip in self.mac_list.items() ]) print '%d *unique* nodes in network' % len(self.mac_list) -- cgit v1.2.3 From 5a55c1b82a26244fb8a2584fa35887d9637bd2e2 Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Tue, 18 Jan 2011 01:48:38 +0100 Subject: fixed logging bug,updated protocol --- main.py | 22 ++++++++++++++++------ snmp_users.py | 4 ++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/main.py b/main.py index 868b5f7e..bb463d3b 100644 --- a/main.py +++ b/main.py @@ -1,19 +1,28 @@ #!/usr/bin/env python2 -import pika -import json,argparse -from snmp_users import snmp_users + import logging logging.basicConfig(level=logging.INFO) log = logging.getLogger('snmp_exchange') +import pika +import json,argparse,hashlib,sys,time +from snmp_users import snmp_users + SNMP_EXCHANGE='snmp_src' +PROTO_VERSION='1' -parser = argparse.ArgumentParser(description='generates dummy package on given exchange against AMQP') +parser = argparse.ArgumentParser(description='Generates a list of mac-addresses currently in the network via snmp ') parser.add_argument('--host',default='141.31.8.11', help='AMQP host ip address') parser.add_argument('--port',type=int,default=5672, help='AMQP host port') parser.add_argument('-u','--username',default='guest', help='AMQP username') parser.add_argument('-p','--password',default='guest', help='AMQP password') parser.add_argument('-r','--repeat',type=int,default=20, help='SNMP_Polling Delay') +parser.add_argument('--unique-key',action='store_true', help='Unique Key') +args = parser.parse_args() +if args.unique_key: + print hashlib.sha1(PROTO_VERSION+args.host+str(args.port)).hexdigest() + sys.exit(0) + args = parser.parse_args() connection = pika.AsyncoreConnection(pika.ConnectionParameters( @@ -24,9 +33,9 @@ channel = connection.channel() channel.exchange_declare(exchange=SNMP_EXCHANGE, type='fanout') -log.info('Starting StatsForUser Module (mongodb)') +log.info('Starting up snmp_users') s = snmp_users() -print ' [*] Sending Messages in Intervals. To exit press CTRL+C' +print ' Sending Messages in Intervals. To exit press CTRL+C' while True: log.info("collecting data from network") ret = s.collect() @@ -35,3 +44,4 @@ while True: channel.basic_publish(exchange=SNMP_EXCHANGE, routing_key='', body=json.dumps(data)) + time.sleep(args.repeat) diff --git a/snmp_users.py b/snmp_users.py index 6eb5c33c..8e2fb05d 100755 --- a/snmp_users.py +++ b/snmp_users.py @@ -45,11 +45,11 @@ class snmp_users: if mac in self.mac_list.keys(): log.info( "%s already assigned for ip %s (new IP %s) " % ( mac ,self.mac_list[mac], ip)) - self.mac_list[mac]['counter'] +=1 + self.mac_list[mac].append ( ip) continue else: log.debug("%s => %s" % (mac,ip)) - self.mac_list[mac] = { 'ip' : ip, 'counter' : 1} + self.mac_list[mac] = [ ip ] else: log.warning("Verification failed %s => %s" % (mac,ip)) -- cgit v1.2.3 From e7b3ba6b4439b4ae046b7be54a2d0bd904642745 Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Sun, 23 Jan 2011 00:47:21 +0100 Subject: fixed output --- arping.py | 2 +- snmp_users.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arping.py b/arping.py index ee96c9aa..816a3f46 100644 --- a/arping.py +++ b/arping.py @@ -8,7 +8,7 @@ try: raise Exception('no root permissions') from scapy.all import * #might throws "no such module" - def arpingy(iprange="10.42.1.0/24",iface='eth0'): + def arpingy(iprange="10.42.1.0/24",iface='wlan0'): log.debug("pinging"+ iprange) """Arping function takes IP Address or Network, returns nested mac/ip list""" try: diff --git a/snmp_users.py b/snmp_users.py index 8e2fb05d..cb31dab6 100755 --- a/snmp_users.py +++ b/snmp_users.py @@ -77,8 +77,8 @@ class snmp_users: return self.mac_list def print_results(self): log.debug('printing results:') - print '\n'.join([ mac + " => " + ip['ip'] + " ( %d active leases )" % - ip['counter'] for mac,ip in self.mac_list.items() ]) + print '\n'.join([ mac + " => %s" % + str(ips) for mac,ips in self.mac_list.items() ]) print '%d *unique* nodes in network' % len(self.mac_list) -- cgit v1.2.3 From 43f2eb6e5492c0fd0797785b3d3b258e2a7a2169 Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Sun, 23 Jan 2011 06:35:48 +0100 Subject: added parallel arping,refactoring --- src/arping.py | 30 +++++++++++++++++ src/main.py | 1 + src/snmp_users.py | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 src/arping.py create mode 100644 src/main.py create mode 100755 src/snmp_users.py diff --git a/src/arping.py b/src/arping.py new file mode 100644 index 00000000..1846f474 --- /dev/null +++ b/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/src/main.py b/src/main.py new file mode 100644 index 00000000..0e1d5dde --- /dev/null +++ b/src/main.py @@ -0,0 +1 @@ +#!/usr/bin/python2 diff --git a/src/snmp_users.py b/src/snmp_users.py new file mode 100755 index 00000000..1d6cf9be --- /dev/null +++ b/src/snmp_users.py @@ -0,0 +1,98 @@ +#!/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" : "10.42.0.1", + "community" : "shammunity", + "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,config={}): + Configurable.__init__(self,DEFAULT_CONFIG) + self.load_conf(config) + + def call_external(self): + """returns an array of lines produced by snmpwalk """ + conf = self.config['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 arping_parallel(self,data): + conf = self.config['arping'] + if conf['active']: + p = Pool(10) + tmp = [ {'iprange':dat[0],'iface':conf['dev']} for dat in data] + try: + return filter(lambda x:x , p.map(arping_helper, tmp)) + 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) + macs = self.verify(data) + self.print_results(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) + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + a = snmp_users() + a.collect() -- cgit v1.2.3 From 5fb4705362ab694eb84b21f1389c6ca6bc5e4d8a Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Sun, 30 Jan 2011 05:46:39 +0100 Subject: updated to something actually working --- src/arping.py | 2 +- src/main.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/snmp_users.py | 15 +++++++++------ 3 files changed, 60 insertions(+), 8 deletions(-) mode change 100644 => 100755 src/main.py diff --git a/src/arping.py b/src/arping.py index 1846f474..11fb81a9 100644 --- a/src/arping.py +++ b/src/arping.py @@ -9,7 +9,7 @@ try: from scapy.all import * #might throws "no such module" def arpingy(iprange="10.42.1.0/24",iface='eth0'): - log.debug("pinging"+ str(iprange)) + log.debug("pinging "+ str(iprange)) """Arping function takes IP Address or Network, returns nested mac/ip list""" try: conf.verb=0 diff --git a/src/main.py b/src/main.py old mode 100644 new mode 100755 index 0e1d5dde..2d9bb206 --- a/src/main.py +++ b/src/main.py @@ -1 +1,50 @@ -#!/usr/bin/python2 +#!/usr/bin/env python2 + +import logging +logging.basicConfig(level=logging.INFO) +log = logging.getLogger('snmp_exchange') + +import pika +import json,argparse,hashlib,sys,time +from snmp_users import snmp_users + +SNMP_EXCHANGE='snmp_src' +PROTO_VERSION='1' + +parser = argparse.ArgumentParser(description='Generates a list of mac-addresses currently in the network via snmp ') +parser.add_argument('--host',default='141.31.8.11', help='AMQP host ip address') +parser.add_argument('--port',type=int,default=5672, help='AMQP host port') +parser.add_argument('-u','--username',default='guest', help='AMQP username') +parser.add_argument('-p','--password',default='guest', help='AMQP password') +parser.add_argument('-r','--repeat',type=int,default=20, help='SNMP_Polling Delay') +parser.add_argument('--unique-key',action='store_true', help='Unique Key') +args = parser.parse_args() +if args.unique_key: + print hashlib.sha1(PROTO_VERSION+args.host+str(args.port)).hexdigest() + sys.exit(0) + +args = parser.parse_args() + +connection = pika.AsyncoreConnection(pika.ConnectionParameters( + credentials = pika.PlainCredentials(args.username,args.password), + host=args.host,port=args.port)) +channel = connection.channel() + +channel.exchange_declare(exchange=SNMP_EXCHANGE, + type='fanout') + +log.info('Starting up snmp_users') +s = 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.info("writing data to queue : %s" % data) + channel.basic_publish(exchange=SNMP_EXCHANGE, + routing_key='', + body=json.dumps(data)) + time.sleep(args.repeat) +except : + print "something happened :(" diff --git a/src/snmp_users.py b/src/snmp_users.py index 1d6cf9be..1f189d78 100755 --- a/src/snmp_users.py +++ b/src/snmp_users.py @@ -8,8 +8,8 @@ log = logging.getLogger('snmp_users') DEFAULT_CONFIG= { "snmp" : { - "server" : "10.42.0.1", - "community" : "shammunity", + "server" : "127.0.0.1", + "community" : "community", "tree" : "1.3.6.1.2.1.3.1.1.2" }, "arping" : { @@ -55,8 +55,8 @@ class snmp_users(Configurable): 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 - + macl = self.mac_list = {} + for ip,mac in new: # fill the mac_list if not macl.get(mac,None): macl[mac] = [] @@ -68,6 +68,7 @@ class snmp_users(Configurable): """ 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) + print arp_data self.update_results(arp_data) def arping_parallel(self,data): @@ -76,7 +77,7 @@ class snmp_users(Configurable): p = Pool(10) tmp = [ {'iprange':dat[0],'iface':conf['dev']} for dat in data] try: - return filter(lambda x:x , p.map(arping_helper, tmp)) + return filter(lambda x:x , p.map(arping_helper, tmp)) except Exception as e: log.warning("Something happened,falling back to original data: "+ str(e)) return data @@ -85,7 +86,8 @@ class snmp_users(Configurable): output = self.call_external() data = self.parse_output(output) macs = self.verify(data) - self.print_results(self.mac_list) + #self.print_results(self.mac_list) + return self.mac_list def print_results(self,macs): log.debug('printing results:') print '\n'.join([ mac + " => %s" % @@ -96,3 +98,4 @@ if __name__ == "__main__": logging.basicConfig(level=logging.INFO) a = snmp_users() a.collect() + a.print_results(a.mac_list) -- cgit v1.2.3 From 0a4dc6e293738b5bff1e94f0f36dcf4da706b34d Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Sun, 30 Jan 2011 22:19:57 +0100 Subject: cleaned up repository --- arping.py | 31 --------------------- main.py | 47 ------------------------------- snmp_users.py | 89 ----------------------------------------------------------- 3 files changed, 167 deletions(-) delete mode 100644 arping.py delete mode 100644 main.py delete mode 100755 snmp_users.py diff --git a/arping.py b/arping.py deleted file mode 100644 index 816a3f46..00000000 --- a/arping.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/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='wlan0'): - log.debug("pinging"+ 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) - collection.append(result) - return collection - 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): - return True diff --git a/main.py b/main.py deleted file mode 100644 index bb463d3b..00000000 --- a/main.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python2 - -import logging -logging.basicConfig(level=logging.INFO) -log = logging.getLogger('snmp_exchange') - -import pika -import json,argparse,hashlib,sys,time -from snmp_users import snmp_users - -SNMP_EXCHANGE='snmp_src' -PROTO_VERSION='1' - -parser = argparse.ArgumentParser(description='Generates a list of mac-addresses currently in the network via snmp ') -parser.add_argument('--host',default='141.31.8.11', help='AMQP host ip address') -parser.add_argument('--port',type=int,default=5672, help='AMQP host port') -parser.add_argument('-u','--username',default='guest', help='AMQP username') -parser.add_argument('-p','--password',default='guest', help='AMQP password') -parser.add_argument('-r','--repeat',type=int,default=20, help='SNMP_Polling Delay') -parser.add_argument('--unique-key',action='store_true', help='Unique Key') -args = parser.parse_args() -if args.unique_key: - print hashlib.sha1(PROTO_VERSION+args.host+str(args.port)).hexdigest() - sys.exit(0) - -args = parser.parse_args() - -connection = pika.AsyncoreConnection(pika.ConnectionParameters( - credentials = pika.PlainCredentials(args.username,args.password), - host=args.host,port=args.port)) -channel = connection.channel() - -channel.exchange_declare(exchange=SNMP_EXCHANGE, - type='fanout') - -log.info('Starting up snmp_users') -s = snmp_users() -print ' Sending Messages in Intervals. To exit press CTRL+C' -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) - channel.basic_publish(exchange=SNMP_EXCHANGE, - routing_key='', - body=json.dumps(data)) - time.sleep(args.repeat) diff --git a/snmp_users.py b/snmp_users.py deleted file mode 100755 index cb31dab6..00000000 --- a/snmp_users.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/python2 -import subprocess,re -import logging -from arping import arpingy -log = logging.getLogger('snmp_users') - -class snmp_users: - mac_list = {} - - def __init__(self,server='10.42.0.1',community='shammunity'): - self.server = server - self.community = community - - def call_external(self): - """ creates a list of lines produced by snmpwal - """ - out = subprocess.Popen( - ['snmpwalk', - '-v2c', - '-c',self.community, - self.server, - '1.3.6.1.2.1.3.1.1.2'], - stdout=subprocess.PIPE).communicate()[0] - return out.split('\n') - - def parse_output(self,output): - """ parses output lines produced by snmpwalk""" - for i in output: - if i == '': - continue - - ip,mac = re.sub(r'.*\.(\d+\.\d+\.\d+\.\d+) = Hex-STRING: ([ 0-9A-F]*) ', - r'\1 : \2',i).split(' : ') - - verified = False - if self.verify_data(mac,ip,arpingy(ip)): - log.info("verfied by arping %s => %s" % (mac,ip)) - verified = True - - #elif self.verify_data(mac,ip,pingy(ip) ): builds up onto arp'ing... - # log.info("verfied by fallback ping %s => %s" % (mac,ip)) - # verfied = True - - if verified: - if mac in self.mac_list.keys(): - log.info( "%s already assigned for ip %s (new IP %s) " % - ( mac ,self.mac_list[mac], ip)) - self.mac_list[mac].append ( ip) - continue - else: - log.debug("%s => %s" % (mac,ip)) - self.mac_list[mac] = [ ip ] - else: - log.warning("Verification failed %s => %s" % (mac,ip)) - - def verify_data(self,mac,ip,ret): - """ Verifies ip and mac via ARP Scan """ - mac = ':'.join(mac.split()) - log.debug(ret) - - if type(ret) == type(True): - return True - elif ret != []: - ret = ret[0] - ret_mac = ret[1].upper() - if ret_mac == mac: - return True - else: - log.info('return mac not equal to expected, %s != %s' % (ret_mac,mac)) - else: - return False - - def collect(self): - output = self.call_external() - self.parse_output(output) - self.print_results() - return self.mac_list - def print_results(self): - log.debug('printing results:') - print '\n'.join([ mac + " => %s" % - str(ips) for mac,ips in self.mac_list.items() ]) - print '%d *unique* nodes in network' % len(self.mac_list) - - -if __name__ == "__main__": - logging.basicConfig(level=logging.INFO) - a = snmp_users() - a.collect() - -- cgit v1.2.3 From 1da944a41a757785a3e7e26656629072dc44f619 Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Sun, 30 Jan 2011 22:21:03 +0100 Subject: now using python-genericore --- src/main.py | 54 ++++++++++++++++++------------------------------------ 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/src/main.py b/src/main.py index 2d9bb206..473729f4 100755 --- a/src/main.py +++ b/src/main.py @@ -1,50 +1,32 @@ #!/usr/bin/env python2 - -import logging -logging.basicConfig(level=logging.INFO) -log = logging.getLogger('snmp_exchange') - -import pika -import json,argparse,hashlib,sys,time +import sys,json,time from snmp_users import snmp_users +import logging +import genericore as gen +log = logging.getLogger('mail_proc_main') +PROTO_VERSION = 1 +DESCRIPTION = 'performes statistical analysis against mails from stream' -SNMP_EXCHANGE='snmp_src' -PROTO_VERSION='1' - -parser = argparse.ArgumentParser(description='Generates a list of mac-addresses currently in the network via snmp ') -parser.add_argument('--host',default='141.31.8.11', help='AMQP host ip address') -parser.add_argument('--port',type=int,default=5672, help='AMQP host port') -parser.add_argument('-u','--username',default='guest', help='AMQP username') -parser.add_argument('-p','--password',default='guest', help='AMQP password') -parser.add_argument('-r','--repeat',type=int,default=20, help='SNMP_Polling Delay') -parser.add_argument('--unique-key',action='store_true', help='Unique Key') -args = parser.parse_args() -if args.unique_key: - print hashlib.sha1(PROTO_VERSION+args.host+str(args.port)).hexdigest() - sys.exit(0) -args = parser.parse_args() +# set up instances of needed modules +conf = gen.Configurator(PROTO_VERSION,DESCRIPTION) +amqp = gen.auto_amqp() +s = snmp_users() # the magic mail parsing class -connection = pika.AsyncoreConnection(pika.ConnectionParameters( - credentials = pika.PlainCredentials(args.username,args.password), - host=args.host,port=args.port)) -channel = connection.channel() +conf.configure([amqp,s]) #set up parser and eval parsed stuff -channel.exchange_declare(exchange=SNMP_EXCHANGE, - type='fanout') +# start network connections +amqp.create_connection() log.info('Starting up snmp_users') -s = 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.info("writing data to queue : %s" % data) - channel.basic_publish(exchange=SNMP_EXCHANGE, - routing_key='', - body=json.dumps(data)) - time.sleep(args.repeat) -except : - print "something happened :(" + 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) -- cgit v1.2.3 From 1e3dc77753cb78493f90006ddfb048bc2b13560e Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Sun, 30 Jan 2011 22:22:55 +0100 Subject: updated snmp_users added populate/eval parser for compatibility fixed Pooling bug (not cleaning up the thread pool after using) fixed bug to miss own address in the results --- src/snmp_users.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/snmp_users.py b/src/snmp_users.py index 1f189d78..12c6efb9 100755 --- a/src/snmp_users.py +++ b/src/snmp_users.py @@ -24,7 +24,7 @@ def arping_helper(dic): class snmp_users(Configurable): mac_list = {} - def __init__(self,config={}): + def __init__(self,config=None): Configurable.__init__(self,DEFAULT_CONFIG) self.load_conf(config) @@ -68,16 +68,25 @@ class snmp_users(Configurable): """ 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) - print arp_data self.update_results(arp_data) + def get_own_addr(self): + data = subprocess.Popen(['/sbin/ifconfig',self.config['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['arping'] if conf['active']: - p = Pool(10) tmp = [ {'iprange':dat[0],'iface':conf['dev']} for dat in data] try: - return filter(lambda x:x , p.map(arping_helper, tmp)) + 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 @@ -85,17 +94,26 @@ class snmp_users(Configurable): def collect(self): output = self.call_external() data = self.parse_output(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) -- cgit v1.2.3 From da06f1c3d243477e7481c2cc07d86843b14a65a4 Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Sun, 30 Jan 2011 22:23:45 +0100 Subject: added run script --- bin/run.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 bin/run.sh diff --git a/bin/run.sh b/bin/run.sh new file mode 100755 index 00000000..6da3d059 --- /dev/null +++ b/bin/run.sh @@ -0,0 +1,5 @@ +#!/bin/bash +echo basedir $0 +BINDIR="`dirname $0`/../src" + +python2 "$BINDIR/main.py" $@ -- cgit v1.2.3 From c40db19a0214bdc6aa4807d3f704815fad833992 Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Mon, 31 Jan 2011 22:16:58 +0100 Subject: updated code to work again Added changes to make it work with python-genericore version 6.0 Added example configuration --- .gitignore | 1 + TODO.md | 4 ++++ conf/example.json | 22 ++++++++++++++++++++++ src/main.py | 7 ++++--- src/snmp_users.py | 17 ++++++++++------- 5 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 .gitignore create mode 100644 TODO.md create mode 100644 conf/example.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0d20b648 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/TODO.md b/TODO.md new file mode 100644 index 00000000..dfefa9a0 --- /dev/null +++ b/TODO.md @@ -0,0 +1,4 @@ +BUGS +===== +- an exception is thrown but handled wrong when snmp servers and arping is + unreachable diff --git a/conf/example.json b/conf/example.json new file mode 100644 index 00000000..f34c20f0 --- /dev/null +++ b/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/src/main.py b/src/main.py index 473729f4..c70bffd4 100755 --- a/src/main.py +++ b/src/main.py @@ -3,15 +3,16 @@ import sys,json,time from snmp_users import snmp_users import logging import genericore as gen -log = logging.getLogger('mail_proc_main') +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() -s = snmp_users() # the magic mail parsing class +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 diff --git a/src/snmp_users.py b/src/snmp_users.py index 12c6efb9..871ed9dd 100755 --- a/src/snmp_users.py +++ b/src/snmp_users.py @@ -24,13 +24,15 @@ def arping_helper(dic): class snmp_users(Configurable): mac_list = {} - def __init__(self,config=None): - Configurable.__init__(self,DEFAULT_CONFIG) + 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['snmp'] + conf = self.config[self.NAME]['snmp'] out = subprocess.Popen( ['snmpwalk', @@ -56,12 +58,10 @@ class snmp_users(Configurable): """ 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): @@ -69,14 +69,15 @@ class snmp_users(Configurable): [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['arping']['dev']], + 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['arping'] + conf = self.config[self.NAME]['arping'] if conf['active']: tmp = [ {'iprange':dat[0],'iface':conf['dev']} for dat in data] try: @@ -94,6 +95,8 @@ class snmp_users(Configurable): 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) -- cgit v1.2.3 From 56cbb651fa8d5fd6c467b37da4faf745e625ce6c Mon Sep 17 00:00:00 2001 From: Felix Richter Date: Mon, 31 Jan 2011 23:02:11 +0100 Subject: added the one and only way to VERSION --- VERSION | 1 + 1 file changed, 1 insertion(+) create mode 100644 VERSION diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..6c50e659 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ ++++++++[>+++++++>+++++++<<-]>.>---.<-. -- cgit v1.2.3 From 483a46be9a90ef46b3f478d62f108d675159cdc6 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 9 May 2011 20:58:09 +0200 Subject: changed repos directory to fit krebs --- README.md | 14 ----- TODO.md | 4 -- VERSION | 1 - bin/run.sh | 5 -- conf/example.json | 22 ------- modules/people/README.md | 14 +++++ modules/people/TODO.md | 4 ++ modules/people/VERSION | 1 + modules/people/bin/run.sh | 5 ++ modules/people/conf/example.json | 22 +++++++ modules/people/src/arping.py | 30 ++++++++++ modules/people/src/main.py | 33 +++++++++++ modules/people/src/snmp_users.py | 122 +++++++++++++++++++++++++++++++++++++++ src/arping.py | 30 ---------- src/main.py | 33 ----------- src/snmp_users.py | 122 --------------------------------------- 16 files changed, 231 insertions(+), 231 deletions(-) delete mode 100644 README.md delete mode 100644 TODO.md delete mode 100644 VERSION delete mode 100755 bin/run.sh delete mode 100644 conf/example.json create mode 100644 modules/people/README.md create mode 100644 modules/people/TODO.md create mode 100644 modules/people/VERSION create mode 100755 modules/people/bin/run.sh create mode 100644 modules/people/conf/example.json create mode 100644 modules/people/src/arping.py create mode 100755 modules/people/src/main.py create mode 100755 modules/people/src/snmp_users.py delete mode 100644 src/arping.py delete mode 100755 src/main.py delete mode 100755 src/snmp_users.py diff --git a/README.md b/README.md deleted file mode 100644 index d28100d3..00000000 --- a/README.md +++ /dev/null @@ -1,14 +0,0 @@ -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/TODO.md b/TODO.md deleted file mode 100644 index dfefa9a0..00000000 --- a/TODO.md +++ /dev/null @@ -1,4 +0,0 @@ -BUGS -===== -- an exception is thrown but handled wrong when snmp servers and arping is - unreachable diff --git a/VERSION b/VERSION deleted file mode 100644 index 6c50e659..00000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -+++++++[>+++++++>+++++++<<-]>.>---.<-. diff --git a/bin/run.sh b/bin/run.sh deleted file mode 100755 index 6da3d059..00000000 --- a/bin/run.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -echo basedir $0 -BINDIR="`dirname $0`/../src" - -python2 "$BINDIR/main.py" $@ diff --git a/conf/example.json b/conf/example.json deleted file mode 100644 index f34c20f0..00000000 --- a/conf/example.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "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/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) diff --git a/src/arping.py b/src/arping.py deleted file mode 100644 index 11fb81a9..00000000 --- a/src/arping.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/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/src/main.py b/src/main.py deleted file mode 100755 index c70bffd4..00000000 --- a/src/main.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/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/src/snmp_users.py b/src/snmp_users.py deleted file mode 100755 index 871ed9dd..00000000 --- a/src/snmp_users.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/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) -- cgit v1.2.3