Commit 8177cdb1 authored by Bertrone Matteo's avatar Bertrone Matteo

http filter example

parent b0950589
......@@ -2,7 +2,8 @@
Write an eBPF application that parses HTTP packets and extracts (and prints on screen) the URL contained in the GET/POST request.
[https://github.com/netgroup-polito/ebpf-test](https://github.com/netgroup-polito/ebpf-test)
[eBPF HTTP Filter - Short Presentation](https://github.com/iovisor/bpf-docs/blob/master/ebpf_http_filter.pdf)
[Original Projct](https://github.com/netgroup-polito/ebpf-test)
#Usage Example
......@@ -27,13 +28,12 @@ Matching packets are forwarded to user space, others dropped by the filter.<br /
<br />
Python script reads filtered raw packets from the socket, if necessary reassembles packets belonging to the same session, and prints on stdout the first line of the HTTP GET/POST request. <br />
# Usage
#v1 vs v2
Require:
- BPF Compiler Collection [BCC](https://github.com/iovisor/bcc)
- Follow [INSTALL](https://github.com/iovisor/bcc/blob/master/INSTALL.md) guide
First version is the simple one: if the url is too long (splitted in more than one packet) is truncated.
Second version is quite more complex: if necessary reassembles packets belonging to the same session and prints the complete url.
# To run:
#To run:
```Shell
$ sudo python http-parse.py
......
......@@ -39,7 +39,7 @@ int http_filter(struct __sk_buff *skb) {
struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
//filter IP packets (ethernet type = 0x0800)
if (!(ethernet->type == 0x0800)){
if (!(ethernet->type == 0x0800)) {
goto DROP;
}
......@@ -75,58 +75,58 @@ int http_filter(struct __sk_buff *skb) {
//e.g. tcp->offset = 5 ; TCP Header Length = 5 x 4 byte = 20 byte
tcp_header_length = tcp->offset << 2; //SHL 2 -> *4 multiply
//calculate patload offset and lenght
//calculate patload offset and length
payload_offset = ETH_HLEN + ip_header_length + tcp_header_length;
payload_length = ip->tlen - ip_header_length - tcp_header_length;
//http://stackoverflow.com/questions/25047905/http-request-minimum-size-in-bytes
//minimum lenght of http request is always geater than 7 bytes
//minimum length of http request is always geater than 7 bytes
//avoid invalid access memory
//include empty payload
if(payload_length < 7){
if(payload_length < 7) {
goto DROP;
}
//load firt 7 byte of payload into payload_array
//load firt 7 byte of payload into p (payload_array)
//direct access to skb not allowed
unsigned long payload_array[7];
unsigned long p[7];
int i = 0;
int j = 0;
for (i = payload_offset ; i < (payload_offset + 7) ; i++){
payload_array[j] = load_byte(skb , i);
for (i = payload_offset ; i < (payload_offset + 7) ; i++) {
p[j] = load_byte(skb , i);
j++;
}
//find a match with an HTTP message
//HTTP
if ( (payload_array[0] == 'H') && (payload_array[1] == 'T') && (payload_array[2] == 'T') && (payload_array[3] == 'P')){
if ((p[0] == 'H') && (p[1] == 'T') && (p[2] == 'T') && (p[3] == 'P')) {
goto HTTP_MATCH;
}
//GET
if ( (payload_array[0] == 'G') && (payload_array[1] == 'E') && (payload_array[2] == 'T') ){
if ((p[0] == 'G') && (p[1] == 'E') && (p[2] == 'T')) {
goto HTTP_MATCH;
}
//POST
if ( (payload_array[0] == 'P') && (payload_array[1] == 'O') && (payload_array[2] == 'S') && (payload_array[3] == 'T')){
if ((p[0] == 'P') && (p[1] == 'O') && (p[2] == 'S') && (p[3] == 'T')) {
goto HTTP_MATCH;
}
//PUT
if ( (payload_array[0] == 'P') && (payload_array[1] == 'U') && (payload_array[2] == 'T') ){
if ((p[0] == 'P') && (p[1] == 'U') && (p[2] == 'T')) {
goto HTTP_MATCH;
}
//DELETE
if ( (payload_array[0] == 'D') && (payload_array[1] == 'E') && (payload_array[2] == 'L') && (payload_array[3] == 'E') && (payload_array[4] == 'T') && (payload_array[5] == 'E')){
if ((p[0] == 'D') && (p[1] == 'E') && (p[2] == 'L') && (p[3] == 'E') && (p[4] == 'T') && (p[5] == 'E')) {
goto HTTP_MATCH;
}
//HEAD
if ( (payload_array[0] == 'H') && (payload_array[1] == 'E') && (payload_array[2] == 'A') && (payload_array[3] == 'D')){
if ((p[0] == 'H') && (p[1] == 'E') && (p[2] == 'A') && (p[3] == 'D')) {
goto HTTP_MATCH;
}
//no HTTP match
//check if packet belong to an HTTP session
struct Leaf * lookup_leaf = sessions.lookup(&key);
if(lookup_leaf){
if(lookup_leaf) {
//send packet to userspace
goto KEEP;
}
......
......@@ -109,7 +109,7 @@ local_dictionary = {}
while 1:
#retrieve raw packet from socket
packet_str = os.read(socket_fd,4096) #set packet lenght to max packet lenght on the interface
packet_str = os.read(socket_fd,4096) #set packet length to max packet length on the interface
packet_count += 1
#DEBUG - print raw packet in hex format
......@@ -133,18 +133,18 @@ while 1:
#value to multiply * 4 byte
#e.g. IHL = 5 ; IP Header Length = 5 * 4 byte = 20 byte
#
#Total Lenght: This 16-bit field defines the entire packet size,
#Total length: This 16-bit field defines the entire packet size,
#including header and data, in bytes.
#calculate packet total lenght
total_lenght = packet_bytearray[ETH_HLEN + 2] #load MSB
total_lenght = total_lenght << 8 #shift MSB
total_lenght = total_lenght + packet_bytearray[ETH_HLEN+3] #add LSB
#calculate packet total length
total_length = packet_bytearray[ETH_HLEN + 2] #load MSB
total_length = total_length << 8 #shift MSB
total_length = total_length + packet_bytearray[ETH_HLEN+3] #add LSB
#calculate ip header lenght
#calculate ip header length
ip_header_length = packet_bytearray[ETH_HLEN] #load Byte
ip_header_length = ip_header_length & 0x0F #mask bits 0..3
ip_header_length = ip_header_length << 2 #shift to obtain lenght
ip_header_length = ip_header_length << 2 #shift to obtain length
#retrieve ip source/dest
ip_src_str = packet_str[ETH_HLEN+12:ETH_HLEN+16] #ip source offset 12..15
......@@ -168,10 +168,10 @@ while 1:
#value to multiply * 4 byte
#e.g. DataOffset = 5 ; TCP Header Length = 5 * 4 byte = 20 byte
#calculate tcp header lenght
tcp_header_lenght = packet_bytearray[ETH_HLEN + ip_header_length + 12] #load Byte
tcp_header_lenght = tcp_header_lenght & 0xF0 #mask bit 4..7
tcp_header_lenght = tcp_header_lenght >> 2 #SHR 4 ; SHL 2 -> SHR 2
#calculate tcp header length
tcp_header_length = packet_bytearray[ETH_HLEN + ip_header_length + 12] #load Byte
tcp_header_length = tcp_header_length & 0xF0 #mask bit 4..7
tcp_header_length = tcp_header_length >> 2 #SHR 4 ; SHL 2 -> SHR 2
#retrieve port source/dest
port_src_str = packet_str[ETH_HLEN+ip_header_length:ETH_HLEN+ip_header_length+2]
......@@ -181,7 +181,7 @@ while 1:
port_dst = int(toHex(port_dst_str),16)
#calculate payload offset
payload_offset = ETH_HLEN + ip_header_length + tcp_header_lenght
payload_offset = ETH_HLEN + ip_header_length + tcp_header_length
#payload_string contains only packet payload
payload_string = packet_str[(payload_offset):(len(packet_bytearray))]
......
......@@ -19,7 +19,7 @@ int http_filter(struct __sk_buff *skb) {
struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
//filter IP packets (ethernet type = 0x0800)
if (!(ethernet->type == 0x0800)){
if (!(ethernet->type == 0x0800)) {
goto DROP;
}
......@@ -46,51 +46,51 @@ int http_filter(struct __sk_buff *skb) {
//e.g. tcp->offset = 5 ; TCP Header Length = 5 x 4 byte = 20 byte
tcp_header_length = tcp->offset << 2; //SHL 2 -> *4 multiply
//calculate patload offset and lenght
//calculate patload offset and length
payload_offset = ETH_HLEN + ip_header_length + tcp_header_length;
payload_length = ip->tlen - ip_header_length - tcp_header_length;
//http://stackoverflow.com/questions/25047905/http-request-minimum-size-in-bytes
//minimum lenght of http request is always geater than 7 bytes
//minimum length of http request is always geater than 7 bytes
//avoid invalid access memory
//include empty payload
if(payload_length < 7){
if(payload_length < 7) {
goto DROP;
}
//load firt 7 byte of payload into payload_array
//load firt 7 byte of payload into p (payload_array)
//direct access to skb not allowed
unsigned long payload_array[7];
unsigned long p[7];
int i = 0;
int j = 0;
for (i = payload_offset ; i < (payload_offset + 7) ; i++){
payload_array[j] = load_byte(skb , i);
for (i = payload_offset ; i < (payload_offset + 7) ; i++) {
p[j] = load_byte(skb , i);
j++;
}
//find a match with an HTTP message
//HTTP
if ( (payload_array[0] == 'H') && (payload_array[1] == 'T') && (payload_array[2] == 'T') && (payload_array[3] == 'P')){
if ((p[0] == 'H') && (p[1] == 'T') && (p[2] == 'T') && (p[3] == 'P')) {
goto KEEP;
}
//GET
if ( (payload_array[0] == 'G') && (payload_array[1] == 'E') && (payload_array[2] == 'T') ){
if ((p[0] == 'G') && (p[1] == 'E') && (p[2] == 'T')) {
goto KEEP;
}
//POST
if ( (payload_array[0] == 'P') && (payload_array[1] == 'O') && (payload_array[2] == 'S') && (payload_array[3] == 'T')){
if ((p[0] == 'P') && (p[1] == 'O') && (p[2] == 'S') && (p[3] == 'T')) {
goto KEEP;
}
//PUT
if ( (payload_array[0] == 'P') && (payload_array[1] == 'U') && (payload_array[2] == 'T') ){
if ((p[0] == 'P') && (p[1] == 'U') && (p[2] == 'T')) {
goto KEEP;
}
//DELETE
if ( (payload_array[0] == 'D') && (payload_array[1] == 'E') && (payload_array[2] == 'L') && (payload_array[3] == 'E') && (payload_array[4] == 'T') && (payload_array[5] == 'E')){
if ((p[0] == 'D') && (p[1] == 'E') && (p[2] == 'L') && (p[3] == 'E') && (p[4] == 'T') && (p[5] == 'E')) {
goto KEEP;
}
//HEAD
if ( (payload_array[0] == 'H') && (payload_array[1] == 'E') && (payload_array[2] == 'A') && (payload_array[3] == 'D')){
if ((p[0] == 'H') && (p[1] == 'E') && (p[2] == 'A') && (p[3] == 'D')) {
goto KEEP;
}
......@@ -105,4 +105,4 @@ int http_filter(struct __sk_buff *skb) {
DROP:
return 0;
}
}
\ No newline at end of file
......@@ -64,18 +64,18 @@ while 1:
#value to multiply * 4 byte
#e.g. IHL = 5 ; IP Header Length = 5 * 4 byte = 20 byte
#
#Total Lenght: This 16-bit field defines the entire packet size,
#Total length: This 16-bit field defines the entire packet size,
#including header and data, in bytes.
#calculate packet total lenght
total_lenght = packet_bytearray[ETH_HLEN + 2] #load MSB
total_lenght = total_lenght << 8 #shift MSB
total_lenght = total_lenght + packet_bytearray[ETH_HLEN+3] #add LSB
#calculate packet total length
total_length = packet_bytearray[ETH_HLEN + 2] #load MSB
total_length = total_length << 8 #shift MSB
total_length = total_length + packet_bytearray[ETH_HLEN+3] #add LSB
#calculate ip header lenght
#calculate ip header length
ip_header_length = packet_bytearray[ETH_HLEN] #load Byte
ip_header_length = ip_header_length & 0x0F #mask bits 0..3
ip_header_length = ip_header_length << 2 #shift to obtain lenght
ip_header_length = ip_header_length << 2 #shift to obtain length
#TCP HEADER
#https://www.rfc-editor.org/rfc/rfc793.txt
......@@ -92,13 +92,13 @@ while 1:
#value to multiply * 4 byte
#e.g. DataOffset = 5 ; TCP Header Length = 5 * 4 byte = 20 byte
#calculate tcp header lenght
tcp_header_lenght = packet_bytearray[ETH_HLEN + ip_header_length + 12] #load Byte
tcp_header_lenght = tcp_header_lenght & 0xF0 #mask bit 4..7
tcp_header_lenght = tcp_header_lenght >> 2 #SHR 4 ; SHL 2 -> SHR 2
#calculate tcp header length
tcp_header_length = packet_bytearray[ETH_HLEN + ip_header_length + 12] #load Byte
tcp_header_length = tcp_header_length & 0xF0 #mask bit 4..7
tcp_header_length = tcp_header_length >> 2 #SHR 4 ; SHL 2 -> SHR 2
#calculate payload offset
payload_offset = ETH_HLEN + ip_header_length + tcp_header_lenght
payload_offset = ETH_HLEN + ip_header_length + tcp_header_length
#print first line of the HTTP GET/POST request
#line ends with 0xOD 0xOA (\r\n)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment