mirror of
https://github.com/h3xduck/TripleCross.git
synced 2025-12-24 18:33:08 +08:00
Updated project structure, and added new list for the next incoming feature.
This commit is contained in:
63
src/ebpf/include/common/common_utils.h
Normal file
63
src/ebpf/include/common/common_utils.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef __COMMON_UTILS_H__
|
||||
#define __COMMON_UTILS_H__
|
||||
|
||||
/**
|
||||
* Compares two strings.
|
||||
* Yes, we cannot use strcmp from ebpf.
|
||||
* https://github.com/iovisor/bcc/issues/691
|
||||
*
|
||||
* Misteriouslly we can from xdp_filter, but it might not work somewhere else.
|
||||
* However it is the verifier which does not let us call strncmp without
|
||||
* additional checks so we will use this one anyway.
|
||||
*
|
||||
* @param str1
|
||||
* @param str1len //Just to please the ebpf verifier
|
||||
* @param str2
|
||||
* @param str2len //Just to please the ebpf verifier
|
||||
* @return 0 if equal, -1 if false
|
||||
*/
|
||||
static __always_inline int str_n_compare(char* str1, int str1len, char* str2, int str2len, int size){
|
||||
for(int ii = 0; ii < size; ii++){
|
||||
if(str1len<ii){
|
||||
return -1;
|
||||
}
|
||||
if(str2len<ii){
|
||||
return -1;
|
||||
}
|
||||
if (str1[ii] != str2[ii]){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of strncpy from the Linux Kernel.
|
||||
* strncpy - Copy a length-limited, C-string
|
||||
* @dest: Where to copy the string to
|
||||
* @src: Where to copy the string from
|
||||
* @count: The maximum number of bytes to copy
|
||||
*
|
||||
* The result is not %NUL-terminated if the source exceeds
|
||||
* @count bytes.
|
||||
*
|
||||
* In the case where the length of @src is less than that of
|
||||
* count, the remainder of @dest will be padded with %NUL.
|
||||
*
|
||||
*/
|
||||
static __always_inline char* str_n_copy(char *dest, const char *src, int count){
|
||||
char *tmp = dest;
|
||||
|
||||
while (count) {
|
||||
if ((*tmp = *src) != 0)
|
||||
src++;
|
||||
tmp++;
|
||||
count--;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
59
src/ebpf/include/packet/packet_manager.h
Normal file
59
src/ebpf/include/packet/packet_manager.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef __PACKET_MANAGER_H__
|
||||
#define __PACKET_MANAGER_H__
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
/* BOUND CHECKING*/
|
||||
|
||||
static __always_inline int ethernet_header_bound_check(struct ethhdr *eth, void* data_end){
|
||||
if ((void *)eth + sizeof(struct ethhdr) > data_end){
|
||||
return -1;
|
||||
}
|
||||
return 0; //OK
|
||||
}
|
||||
|
||||
static __always_inline int ip_header_bound_check(struct iphdr* ip, void* data_end){
|
||||
if ((void *)ip + sizeof(*ip) > data_end){
|
||||
return -1;
|
||||
}
|
||||
return 0; //OK
|
||||
}
|
||||
|
||||
static __always_inline int tcp_header_bound_check(struct tcphdr* tcp, void* data_end){
|
||||
if ((void *)tcp + sizeof(*tcp) > data_end){
|
||||
return -1;
|
||||
}
|
||||
return 0; //OK
|
||||
}
|
||||
|
||||
static __always_inline int tcp_payload_bound_check(char* payload, int payload_size, void* data_end){
|
||||
if ((void*)payload + payload_size > data_end){
|
||||
return -1;
|
||||
}
|
||||
return 0; //OK
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* UTILITIES */
|
||||
|
||||
static __always_inline int get_protocol(void* data){
|
||||
struct ethhdr *eth = data;
|
||||
struct iphdr *ip = data + sizeof(*eth);
|
||||
switch(ip->protocol){
|
||||
case IPPROTO_TCP:
|
||||
return IPPROTO_TCP;
|
||||
case IPPROTO_UDP:
|
||||
return IPPROTO_UDP;
|
||||
default:
|
||||
return -1; //Unknown and not handled.
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline unsigned char* get_payload(struct tcphdr *tcp){
|
||||
return (void *)tcp + tcp->doff*4;
|
||||
}
|
||||
|
||||
#endif
|
||||
67
src/ebpf/include/packet/protocol/ip_helper.h
Normal file
67
src/ebpf/include/packet/protocol/ip_helper.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef __IP_HELPER_H__
|
||||
#define __IP_HELPER_H__
|
||||
|
||||
#include <linux/ip.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
/**
|
||||
* IP checksum calculation.
|
||||
* Following RFC 1071.
|
||||
* In essence 1's complement of 16-bit groups.
|
||||
* Taken from my own library https://github.com/h3xduck/RawTCP_Lib/blob/master/src/packet.c
|
||||
*/
|
||||
static __always_inline unsigned short checksum(unsigned short *addr, int nbytes){
|
||||
long sum = 0;
|
||||
unsigned short checksum;
|
||||
while(nbytes>1){
|
||||
sum += (unsigned short) *addr++;
|
||||
nbytes -= 2;
|
||||
}
|
||||
if(nbytes>0){
|
||||
sum +=htons((unsigned char)*addr);
|
||||
}
|
||||
|
||||
while (sum>>16){
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
}
|
||||
|
||||
checksum = ~sum;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
||||
static __always_inline __u16 csum_fold_helper(__u32 csum)
|
||||
{
|
||||
//return ~((csum & 0xffff) + (csum >> 16));
|
||||
//The following solves some errors where the last summatory overflows
|
||||
#pragma unroll
|
||||
for (int i = 0; i < 4; i ++) {
|
||||
if (csum >> 16){
|
||||
csum = (csum & 0xffff) + (csum >> 16);
|
||||
}
|
||||
}
|
||||
return ~csum;
|
||||
}
|
||||
/**
|
||||
* IP checksum calculation.
|
||||
* Following RFC 1071, using BPFs.*
|
||||
*/
|
||||
static __always_inline void ipv4_csum(void *data_start, int data_size, __u32 *csum)
|
||||
{
|
||||
//WITH EBPF HELPERS
|
||||
bpf_printk("csum: %u for data_start %u, data_size %i\n", *csum, data_start, data_size);
|
||||
|
||||
/*unsigned char* p = (unsigned char*) data_start;
|
||||
for(int ii = 0; ii<20; ii++){
|
||||
bpf_printk("B%i: %x\n", ii, p[ii]);
|
||||
}*/
|
||||
|
||||
*csum = bpf_csum_diff(0, 0, data_start, data_size, *csum);
|
||||
*csum = csum_fold_helper(*csum);
|
||||
}
|
||||
|
||||
#endif
|
||||
41
src/ebpf/include/packet/protocol/tcp_helper.h
Normal file
41
src/ebpf/include/packet/protocol/tcp_helper.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef __TCP_HELPER_H__
|
||||
#define __TCP_HELPER_H__
|
||||
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/ip.h>
|
||||
|
||||
|
||||
static __always_inline int get_tcp_src_port(struct tcphdr *tcp){
|
||||
return ntohs(tcp->source);
|
||||
}
|
||||
|
||||
static __always_inline int get_tcp_dest_port(struct tcphdr *tcp){
|
||||
return ntohs(tcp->dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* TCP checksum calculation.
|
||||
* Following RFC 1071.
|
||||
* In essence 1's complement of 16-bit groups.
|
||||
* Taken from my own library https://github.com/h3xduck/RawTCP_Lib/blob/master/src/segment.c
|
||||
*/
|
||||
static __always_inline unsigned short tcp_checksum(unsigned short *addr, int nbytes){
|
||||
long sum = 0;
|
||||
unsigned short checksum;
|
||||
while(nbytes>1){
|
||||
sum += (unsigned short) *addr++;
|
||||
nbytes -= 2;
|
||||
}
|
||||
if(nbytes>0){
|
||||
sum += htons((unsigned char)*addr);
|
||||
}
|
||||
|
||||
while (sum>>16){
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
}
|
||||
|
||||
checksum = ~sum;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
#endif
|
||||
133
src/ebpf/include/xdp/xdp_helper.h
Normal file
133
src/ebpf/include/xdp/xdp_helper.h
Normal file
@@ -0,0 +1,133 @@
|
||||
#ifndef __XDP_HELPER_H__
|
||||
#define __XDP_HELPER_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
#include "packet/protocol/ip_helper.h"
|
||||
#include "packet/protocol/tcp_helper.h"
|
||||
#include "packet/packet_manager.h"
|
||||
|
||||
static struct expand_return{
|
||||
int code;
|
||||
struct xdp_md *ret_md;
|
||||
void *data;
|
||||
void *data_end;
|
||||
struct ethhdr *eth;
|
||||
struct iphdr *ip;
|
||||
struct tcphdr *tcp;
|
||||
}expand_return;
|
||||
|
||||
/**
|
||||
* Increases the packet payload reserved size by more_bytes bytes
|
||||
* @param ctx XDP hook metadata
|
||||
* @param eth start of ethernet header. Points inside ctx struct
|
||||
* @param ip start of internet protocol header. Points inside ctx struct
|
||||
* @param tcp start of tcp header. Points inside ctx struct
|
||||
* @param more_bytes Number bytes to add
|
||||
* @param
|
||||
*/
|
||||
static __always_inline struct expand_return expand_tcp_packet_payload(struct xdp_md *ctx, struct ethhdr *eth, struct iphdr *ip, struct tcphdr *tcp, int more_bytes){
|
||||
//We might be able to reuse some data from old headers,
|
||||
//but we will have to recompute checksums still
|
||||
struct ethhdr eth_copy;
|
||||
struct iphdr ip_copy;
|
||||
struct tcphdr tcp_copy;
|
||||
|
||||
struct expand_return ret;
|
||||
|
||||
//Copy the header for later before expanding ctx
|
||||
__builtin_memcpy(ð_copy, eth, sizeof(struct ethhdr));
|
||||
__builtin_memcpy(&ip_copy, ip, sizeof(struct iphdr));
|
||||
__builtin_memcpy(&tcp_copy, tcp, sizeof(struct tcphdr));
|
||||
|
||||
if (bpf_xdp_adjust_tail(ctx, (int)(sizeof(char)*more_bytes)) != 0)
|
||||
{
|
||||
//Failed to expand
|
||||
bpf_printk("Failed to expand a tcp packet reserved bytes by %i\n", more_bytes);
|
||||
ret.code = -1;//The rest is undefined
|
||||
return ret;
|
||||
}
|
||||
|
||||
//We must check bounds again, otherwise the verifier gets angry
|
||||
ret.eth = (void*)(long)ctx->data;
|
||||
ret.ip = (void *)ret.eth + sizeof(struct ethhdr);
|
||||
ret.tcp = (void *)ret.ip + sizeof(struct iphdr);
|
||||
void* data = (void*)(long)ctx->data;
|
||||
void* data_end = (void*)(long)ctx->data_end;
|
||||
if(ethernet_header_bound_check(ret.eth, data_end)<0){
|
||||
bpf_printk("Bound check A failed while expanding\n");
|
||||
ret.code = -1;//The rest is undefined
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ip_header_bound_check(ret.ip, data_end)<0){
|
||||
bpf_printk("Bound check B failed while expanding\n");
|
||||
ret.code = -1;//The rest is undefined
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (tcp_header_bound_check(ret.tcp, data_end)){
|
||||
bpf_printk("Bound check C failed while expanding\n");
|
||||
ret.code = -1;//The rest is undefined
|
||||
return ret;
|
||||
}
|
||||
|
||||
//We now have to readjust the packet headers, checksums have changed
|
||||
//Note that we do not care about ctx->data_meta or any other extra field
|
||||
//since we will not be using any communication here
|
||||
__builtin_memcpy((ret.eth), ð_copy, sizeof(struct ethhdr));
|
||||
__builtin_memcpy((ret.ip), &ip_copy, sizeof(struct iphdr));
|
||||
__builtin_memcpy((ret.tcp), &tcp_copy, sizeof(struct tcphdr));
|
||||
|
||||
|
||||
//We modify the fields we care about of the headers
|
||||
bpf_printk("before: %i, checksum %u\n", ret.ip->tot_len, ret.ip->check);
|
||||
ret.ip->tot_len = htons(ntohs(ret.ip->tot_len) + more_bytes);
|
||||
__u32 csum = 0;
|
||||
ret.ip->check = 0;
|
||||
ipv4_csum(ret.ip, sizeof(struct iphdr), &csum);
|
||||
ret.ip->check = csum;
|
||||
bpf_printk("after: %i, checksum %u\n", ret.ip->tot_len, ret.ip->check);
|
||||
ret.ret_md = ctx;
|
||||
ret.code = 0;
|
||||
ret.data = (void *)(long)ctx->data;
|
||||
ret.data_end = (void *)(long)ctx->data_end;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __always_inline void modify_payload(char* payload_org, int payload_size, char* pattern, int pattern_size, void* packet_init, void* packet_limit){
|
||||
if(pattern_size > payload_size || pattern_size + (void*)payload_org>packet_limit || payload_size + (void*)payload_org > packet_limit){
|
||||
bpf_printk("Invalid attempt to substitute the payload A\n");
|
||||
return; //Chicken check
|
||||
}
|
||||
|
||||
if((void*)payload_org + pattern_size > (void*)packet_limit){
|
||||
bpf_printk("Invalid attempt to substitute the payload B\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if((void*)payload_org + pattern_size + (payload_size-pattern_size) > (void*)packet_limit){
|
||||
bpf_printk("Invalid attempt to substitute the payload C\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(payload_size<1 || pattern_size<1){
|
||||
bpf_printk("Invalid attempt to substitute the payload D\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int ii=0; ii<pattern_size; ii++){
|
||||
payload_org[ii] = pattern[ii];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
|
||||
#include "../user/xdp_filter.h"
|
||||
#include "../user/include/xdp_filter.h"
|
||||
#include "../constants/constants.h"
|
||||
|
||||
#include "packet/packet_manager.h"
|
||||
|
||||
Reference in New Issue
Block a user