1#!/usr/bin/python 2# 3# net_monitor.py Aggregates incoming network traffic 4# outputs source ip, destination ip, the number of their network traffic, and current time 5# how to use : net_monitor.py <net_interface> 6# 7# Copyright (c) 2020 YoungEun Choe 8 9from bcc import BPF 10import time 11from ast import literal_eval 12import sys 13 14def help(): 15 print("execute: {0} <net_interface>".format(sys.argv[0])) 16 print("e.g.: {0} eno1\n".format(sys.argv[0])) 17 exit(1) 18 19if len(sys.argv) != 2: 20 help() 21elif len(sys.argv) == 2: 22 INTERFACE = sys.argv[1] 23 24bpf_text = """ 25 26#include <uapi/linux/ptrace.h> 27#include <net/sock.h> 28#include <bcc/proto.h> 29#include <linux/bpf.h> 30 31#define IP_TCP 6 32#define IP_UDP 17 33#define IP_ICMP 1 34#define ETH_HLEN 14 35 36BPF_PERF_OUTPUT(skb_events); 37BPF_HASH(packet_cnt, u64, long, 256); 38 39int packet_monitor(struct __sk_buff *skb) { 40 u8 *cursor = 0; 41 u32 saddr, daddr; 42 long* count = 0; 43 long one = 1; 44 u64 pass_value = 0; 45 46 struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); 47 48 struct ip_t *ip = cursor_advance(cursor, sizeof(*ip)); 49 if (ip->nextp != IP_TCP) 50 { 51 if (ip -> nextp != IP_UDP) 52 { 53 if (ip -> nextp != IP_ICMP) 54 return 0; 55 } 56 } 57 58 saddr = ip -> src; 59 daddr = ip -> dst; 60 61 pass_value = saddr; 62 pass_value = pass_value << 32; 63 pass_value = pass_value + daddr; 64 65 count = packet_cnt.lookup(&pass_value); 66 if (count) // check if this map exists 67 *count += 1; 68 else // if the map for the key doesn't exist, create one 69 { 70 packet_cnt.update(&pass_value, &one); 71 } 72 return -1; 73} 74 75""" 76 77from ctypes import * 78import ctypes as ct 79import sys 80import socket 81import os 82import struct 83 84OUTPUT_INTERVAL = 1 85 86bpf = BPF(text=bpf_text) 87 88function_skb_matching = bpf.load_func("packet_monitor", BPF.SOCKET_FILTER) 89 90BPF.attach_raw_socket(function_skb_matching, INTERFACE) 91 92 # retrieeve packet_cnt map 93packet_cnt = bpf.get_table('packet_cnt') # retrieeve packet_cnt map 94 95def decimal_to_human(input_value): 96 input_value = int(input_value) 97 hex_value = hex(input_value)[2:] 98 pt3 = literal_eval((str('0x'+str(hex_value[-2:])))) 99 pt2 = literal_eval((str('0x'+str(hex_value[-4:-2])))) 100 pt1 = literal_eval((str('0x'+str(hex_value[-6:-4])))) 101 pt0 = literal_eval((str('0x'+str(hex_value[-8:-6])))) 102 result = str(pt0)+'.'+str(pt1)+'.'+str(pt2)+'.'+str(pt3) 103 return result 104 105try: 106 while True : 107 time.sleep(OUTPUT_INTERVAL) 108 packet_cnt_output = packet_cnt.items() 109 output_len = len(packet_cnt_output) 110 print('\n') 111 for i in range(0,output_len): 112 if (len(str(packet_cnt_output[i][0]))) != 30: 113 continue 114 temp = int(str(packet_cnt_output[i][0])[8:-2]) # initial output omitted from the kernel space program 115 temp = int(str(bin(temp))[2:]) # raw file 116 src = int(str(temp)[:32],2) # part1 117 dst = int(str(temp)[32:],2) 118 pkt_num = str(packet_cnt_output[i][1])[7:-1] 119 120 monitor_result = 'source address : ' + decimal_to_human(str(src)) + ' ' + 'destination address : ' + \ 121 decimal_to_human(str(dst)) + ' ' + pkt_num + ' ' + 'time : ' + str(time.localtime()[0])+\ 122 ';'+str(time.localtime()[1]).zfill(2)+';'+str(time.localtime()[2]).zfill(2)+';'+\ 123 str(time.localtime()[3]).zfill(2)+';'+str(time.localtime()[4]).zfill(2)+';'+\ 124 str(time.localtime()[5]).zfill(2) 125 print(monitor_result) 126 127 # time.time() outputs time elapsed since 00:00 hours, 1st, Jan., 1970. 128 packet_cnt.clear() # delete map entires after printing output. confiremd it deletes values and keys too 129 130except KeyboardInterrupt: 131 sys.stdout.close() 132 pass 133 134