134 lines
3.7 KiB
Python
134 lines
3.7 KiB
Python
#!/usr/bin/python
|
|
#
|
|
# net_monitor.py Aggregates incoming network traffic
|
|
# outputs source ip, destination ip, the number of their network traffic, and current time
|
|
# how to use : net_monitor.py <net_interface>
|
|
#
|
|
# Copyright (c) 2020 YoungEun Choe
|
|
|
|
from bcc import BPF
|
|
import time
|
|
from ast import literal_eval
|
|
import sys
|
|
|
|
def help():
|
|
print("execute: {0} <net_interface>".format(sys.argv[0]))
|
|
print("e.g.: {0} eno1\n".format(sys.argv[0]))
|
|
exit(1)
|
|
|
|
if len(sys.argv) != 2:
|
|
help()
|
|
elif len(sys.argv) == 2:
|
|
INTERFACE = sys.argv[1]
|
|
|
|
bpf_text = """
|
|
|
|
#include <uapi/linux/ptrace.h>
|
|
#include <net/sock.h>
|
|
#include <bcc/proto.h>
|
|
#include <linux/bpf.h>
|
|
|
|
#define IP_TCP 6
|
|
#define IP_UDP 17
|
|
#define IP_ICMP 1
|
|
#define ETH_HLEN 14
|
|
|
|
BPF_PERF_OUTPUT(skb_events);
|
|
BPF_HASH(packet_cnt, u64, long, 256);
|
|
|
|
int packet_monitor(struct __sk_buff *skb) {
|
|
u8 *cursor = 0;
|
|
u32 saddr, daddr;
|
|
long* count = 0;
|
|
long one = 1;
|
|
u64 pass_value = 0;
|
|
|
|
struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
|
|
|
|
struct ip_t *ip = cursor_advance(cursor, sizeof(*ip));
|
|
if (ip->nextp != IP_TCP)
|
|
{
|
|
if (ip -> nextp != IP_UDP)
|
|
{
|
|
if (ip -> nextp != IP_ICMP)
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
saddr = ip -> src;
|
|
daddr = ip -> dst;
|
|
|
|
pass_value = saddr;
|
|
pass_value = pass_value << 32;
|
|
pass_value = pass_value + daddr;
|
|
|
|
count = packet_cnt.lookup(&pass_value);
|
|
if (count) // check if this map exists
|
|
*count += 1;
|
|
else // if the map for the key doesn't exist, create one
|
|
{
|
|
packet_cnt.update(&pass_value, &one);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
"""
|
|
|
|
from ctypes import *
|
|
import ctypes as ct
|
|
import sys
|
|
import socket
|
|
import os
|
|
import struct
|
|
|
|
OUTPUT_INTERVAL = 1
|
|
|
|
bpf = BPF(text=bpf_text)
|
|
|
|
function_skb_matching = bpf.load_func("packet_monitor", BPF.SOCKET_FILTER)
|
|
|
|
BPF.attach_raw_socket(function_skb_matching, INTERFACE)
|
|
|
|
# retrieeve packet_cnt map
|
|
packet_cnt = bpf.get_table('packet_cnt') # retrieeve packet_cnt map
|
|
|
|
def decimal_to_human(input_value):
|
|
input_value = int(input_value)
|
|
hex_value = hex(input_value)[2:]
|
|
pt3 = literal_eval((str('0x'+str(hex_value[-2:]))))
|
|
pt2 = literal_eval((str('0x'+str(hex_value[-4:-2]))))
|
|
pt1 = literal_eval((str('0x'+str(hex_value[-6:-4]))))
|
|
pt0 = literal_eval((str('0x'+str(hex_value[-8:-6]))))
|
|
result = str(pt0)+'.'+str(pt1)+'.'+str(pt2)+'.'+str(pt3)
|
|
return result
|
|
|
|
try:
|
|
while True :
|
|
time.sleep(OUTPUT_INTERVAL)
|
|
packet_cnt_output = packet_cnt.items()
|
|
output_len = len(packet_cnt_output)
|
|
print('\n')
|
|
for i in range(0,output_len):
|
|
if (len(str(packet_cnt_output[i][0]))) != 30:
|
|
continue
|
|
temp = int(str(packet_cnt_output[i][0])[8:-2]) # initial output omitted from the kernel space program
|
|
temp = int(str(bin(temp))[2:]) # raw file
|
|
src = int(str(temp)[:32],2) # part1
|
|
dst = int(str(temp)[32:],2)
|
|
pkt_num = str(packet_cnt_output[i][1])[7:-1]
|
|
|
|
monitor_result = 'source address : ' + decimal_to_human(str(src)) + ' ' + 'destination address : ' + \
|
|
decimal_to_human(str(dst)) + ' ' + pkt_num + ' ' + 'time : ' + str(time.localtime()[0])+\
|
|
';'+str(time.localtime()[1]).zfill(2)+';'+str(time.localtime()[2]).zfill(2)+';'+\
|
|
str(time.localtime()[3]).zfill(2)+';'+str(time.localtime()[4]).zfill(2)+';'+\
|
|
str(time.localtime()[5]).zfill(2)
|
|
print(monitor_result)
|
|
|
|
# time.time() outputs time elapsed since 00:00 hours, 1st, Jan., 1970.
|
|
packet_cnt.clear() # delete map entires after printing output. confiremd it deletes values and keys too
|
|
|
|
except KeyboardInterrupt:
|
|
sys.stdout.close()
|
|
pass
|
|
|