1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
#!/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->ver != 4)
return 0;
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
import ipaddress
import ctypes
from datetime import datetime
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):
try:
decimal_ip = int(input_value)
ip_string = str(ipaddress.IPv4Address(decimal_ip))
return ip_string
except ValueError:
return "Invalid input"
try:
while True :
time.sleep(OUTPUT_INTERVAL)
packet_cnt_output = packet_cnt.items()
output_len = len(packet_cnt_output)
current_time = datetime.now()
formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
if output_len != 0:
print('\ncurrent packet nums:')
for i in range(0,output_len):
srcdst = packet_cnt_output[i][0].value
src = (srcdst >> 32) & 0xFFFFFFFF
dst = srcdst & 0xFFFFFFFF
pkt_num = packet_cnt_output[i][1].value
monitor_result = 'source address : ' + decimal_to_human(str(src)) + ' ' + 'destination address : ' + \
decimal_to_human(str(dst)) + ' ' + str(pkt_num) + ' ' + 'time : ' + formatted_time
print(monitor_result)
packet_cnt.clear() # delete map entires after printing output. confiremd it deletes values and keys too
except KeyboardInterrupt:
sys.stdout.close()
pass
|