Last active
September 15, 2020 16:27
-
-
Save time-river/485adc9ec9f0c1f8abd9e16128774ea9 to your computer and use it in GitHub Desktop.
bpfcc dump skb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <uapi/linux/ptrace.h> | |
#include <net/sock.h> | |
#include <bcc/proto.h> | |
#define IP_ICMP 1 | |
#define IP_TCP 6 | |
#define ETH_HLEN 14 | |
/*eBPF program. | |
Filter IP and TCP packets, having payload not empty | |
and containing "HTTP", "GET", "POST" ... as first bytes of payload | |
if the program is loaded as PROG_TYPE_SOCKET_FILTER | |
and attached to a socket | |
return 0 -> DROP the packet | |
return -1 -> KEEP the packet and return it to user space (userspace can read it from the socket_fd ) | |
*/ | |
int http_filter(struct __sk_buff *skb) { | |
u8 *cursor = 0; | |
u64 ts; | |
u32 src_ip, dst_ip; | |
struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); | |
//filter IP packets (ethernet type = 0x0800) | |
if (!(ethernet->type == 0x0800)) { | |
goto DROP; | |
} | |
struct ip_t *ip = cursor_advance(cursor, sizeof(*ip)); | |
//filter TCP packets (ip next protocol = 0x06) | |
if (ip->nextp != IP_ICMP) { | |
goto DROP; | |
} | |
//retrieve ip src/dest and port src/dest of current packet | |
//and save it into struct Key | |
dst_ip = ip->dst; | |
src_ip = ip->src; | |
ts = bpf_ktime_get_ns(); | |
bpf_trace_printk("%lu %x %x\n", ts, src_ip, dst_ip); | |
KEEP: | |
return -1; | |
DROP: | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# | |
#Bertrone Matteo - Polytechnic of Turin | |
#November 2015 | |
# | |
#eBPF application that parses HTTP packets | |
#and extracts (and prints on screen) the URL contained in the GET/POST request. | |
# | |
#eBPF program http_filter is used as SOCKET_FILTER attached to eth0 interface. | |
#only packet of type ip and tcp containing HTTP GET/POST are returned to userspace, others dropped | |
# | |
#python script uses bcc BPF Compiler Collection by iovisor (https://github.com/iovisor/bcc) | |
#and prints on stdout the first line of the HTTP GET/POST request containing the url | |
from __future__ import print_function | |
from bcc import BPF | |
from sys import argv | |
import sys | |
import socket | |
import os | |
#args | |
def usage(): | |
print("USAGE: %s [-i <if_name>]" % argv[0]) | |
print("") | |
print("Try '%s -h' for more options." % argv[0]) | |
exit() | |
#help | |
def help(): | |
print("USAGE: %s [-i <if_name>]" % argv[0]) | |
print("") | |
print("optional arguments:") | |
print(" -h print this help") | |
print(" -i if_name select interface if_name. Default is eth0") | |
print("") | |
print("examples:") | |
print(" http-parse # bind socket to eth0") | |
print(" http-parse -i wlan0 # bind socket to wlan0") | |
exit() | |
#arguments | |
interface="eth0" | |
if len(argv) == 2: | |
if str(argv[1]) == '-h': | |
help() | |
else: | |
usage() | |
if len(argv) == 3: | |
if str(argv[1]) == '-i': | |
interface = argv[2] | |
else: | |
usage() | |
if len(argv) > 3: | |
usage() | |
print ("binding socket to '%s'" % interface) | |
# initialize BPF - load source code from http-parse-simple.c | |
bpf = BPF(src_file = "http-parse-simple.c",debug = 0) | |
#load eBPF program http_filter of type SOCKET_FILTER into the kernel eBPF vm | |
#more info about eBPF program types | |
#http://man7.org/linux/man-pages/man2/bpf.2.html | |
function_http_filter = bpf.load_func("http_filter", BPF.SOCKET_FILTER) | |
#create raw socket, bind it to interface | |
#attach bpf program to socket created | |
BPF.attach_raw_socket(function_http_filter, interface) | |
#get file descriptor of the socket previously created inside BPF.attach_raw_socket | |
#socket_fd = function_http_filter.sock | |
#create python socket object, from the file descriptor | |
#sock = socket.fromfd(socket_fd,socket.PF_PACKET,socket.SOCK_RAW,socket.IPPROTO_IP) | |
#set it as blocking socket | |
#sock.setblocking(True) | |
def inet_ntoa(addr): | |
dq = b'' | |
for i in range(0, 4): | |
dq = dq + str(addr & 0xff).encode() | |
if (i != 3): | |
dq = dq + b'.' | |
addr = addr >> 8 | |
return dq | |
while 1: | |
# packet_str = os.read(socket_fd,2048) | |
(task, pid, cpu, flags, ts, msg) = bpf.trace_fields() | |
(kern_ts, src_ip, dst_ip) = msg.split(b' ') | |
print('ts: {} kern_ts: {} src_ip: {} kern_ip: {}'.format(ts, kern_ts, inet_ntoa(int(src_ip, 16)), inet_ntoa(int(dst_ip, 16)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment