I wrote a script that recurses through a set of Cisco routers in a network, and gets traffic statistics. On the router itself, I have it ping to the loopback address of my host PC, after a traffic threshold, however now I need the script to run. Now I have one of two options. To either trigger the python script via a ping from the router to the loopback, or from an FTP upload to a folder on my PC. Problem with the folder idea is I'm not sure if I can make it run without constantly scanning through the folder. Since network traffic jumps up and down, I'd like to monitor it immediately as the router sends a message(whether it's ftp or ping etc).
Today, i tried a socket listener, but the router doesn't have native support for sending UDP datagrams. Also ping doesn't work with ports. I tried a ip address listener without using a port, currently my knowledge isn't good enough to know how to implement this. I've done socket programming before but not simply listening for ICMP pings(even still I'd have to capture the packet and look at the source IP address to make sure it's sourced from the router.)
Could anyone give me a clue how to implement this? My best preference would be a loopback listening script that captures packets and triggers the script once a source IP is from the router. Any ideas?
Ok, so by reading chapter 3 of Black Hat Python i borrowed their code and am almost done with a working solution. Everything works , except for 1 snag - The listener is printing out both the source ip and destination ip as resolved back to the loopback(in this case the destination). I've tried pinging from the routers, and from cmd by changing the source, the source address always resolved to my loopback address. I checked with wireshark and it showed a different source address, the one I was expecting. I attempted to see if I was looking at echo replies (although this should mean my source pops up as dest), and changed some socket.IPPROTO_ICMP parameters around, as well as toy around with header lengths. It's doing just that. it's printing my source address as my destination loopback. Any thoughts?
class IP:
def __init__(self, buff=None):header = struct.unpack('<BBHHHBBH4s4s4s', buff)self.ver = header[0] >> 4self.ihl = header[0] & 0xFself.tos = header[1]self.len = header[2]self.id = header[3]self.offset = header[4]self.ttl = header[5]self.protocol_num = header[6]self.sum = header[7]self.src = header[8]self.dst = header[9]self.trash = header[10]self.src_address = ipaddress.ip_address(self.src)self.dst_address = ipaddress.ip_address(self.dst)self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"}try:self.protocol = self.protocol_map[self.protocol_num]except Exception as e:print('%s No protocol for %s' % (e, self.protocol_num))self.protocol = str(self.protocol_num)def sniff(host):socket_protocol = socket.IPPROTO_ICMPsniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)sniffer.bind((host, 0))sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)if os.name == 'nt':sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)try:while True:raw_buffer = sniffer.recvfrom(65535)[0]ip_header = IP(raw_buffer[0:24])print(f'Version: {ip_header.ver}')print(f'Header Length: {ip_header.ihl} TTL: {ip_header.ttl}')offset = ip_header.ihl * 4buf = raw_buffer[offset:offset + 8]icmp_header = ICMP(buf)print('ICMP -> Type: %s Code: %s\n' %(icmp_header.type, icmp_header.code))print('Protocol: %s %s -> %s' % (ip_header.protocol,ip_header.src_address,ip_header.dst_address))
host = '192.168.56.1'
IP.sniff(host)