Update project
This commit is contained in:
		
							parent
							
								
									9a67b4f32c
								
							
						
					
					
						commit
						b57efa5cad
					
				
							
								
								
									
										
											BIN
										
									
								
								dns-trace
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								dns-trace
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										20
									
								
								src/common.h
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										20
									
								
								src/common.h
									
									
									
									
									
								
							@ -6,6 +6,10 @@
 | 
			
		||||
#define REQ_QUERY   0x00
 | 
			
		||||
#define REQ_ANSWER  0x01
 | 
			
		||||
 | 
			
		||||
/* See section 2.3.4 RFC 1035 */
 | 
			
		||||
#define MAX_UDP_PAYLOAD 512
 | 
			
		||||
#define MAx_NAME_LEN    255 
 | 
			
		||||
 | 
			
		||||
struct dnshdr {
 | 
			
		||||
    uint16_t transactionID;
 | 
			
		||||
    uint16_t flags;
 | 
			
		||||
@ -15,12 +19,6 @@ struct dnshdr {
 | 
			
		||||
    uint16_t nbAdditionalRRs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*struct dns_query {
 | 
			
		||||
    char *name;
 | 
			
		||||
    uint16_t type;
 | 
			
		||||
    uint16_t class;
 | 
			
		||||
};*/
 | 
			
		||||
 | 
			
		||||
struct event {
 | 
			
		||||
    uint32_t client;
 | 
			
		||||
    int dport;
 | 
			
		||||
@ -30,9 +28,8 @@ struct event {
 | 
			
		||||
    char qname[QNAME_SIZE];
 | 
			
		||||
    uint16_t class;
 | 
			
		||||
    uint16_t type;
 | 
			
		||||
    uint32_t ans[5];
 | 
			
		||||
    uint16_t numAns;
 | 
			
		||||
    uint32_t ttl;
 | 
			
		||||
    unsigned char buf[MAX_UDP_PAYLOAD]; // On stocke la data au format size + data
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct query_section{
 | 
			
		||||
@ -43,9 +40,10 @@ struct query_section{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct dns_answer {
 | 
			
		||||
    char qname[QNAME_SIZE];
 | 
			
		||||
    char ip[32];
 | 
			
		||||
    int ttl;
 | 
			
		||||
    char data[512];
 | 
			
		||||
    uint16_t class;
 | 
			
		||||
    uint16_t type;
 | 
			
		||||
    uint32_t ttl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -148,6 +148,11 @@ static char *mapType(const int type){
 | 
			
		||||
    if (tmp == NULL)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * type DNS defined in RFC:
 | 
			
		||||
     * https://datatracker.ietf.org/doc/html/rfc1035#section-3.2.2
 | 
			
		||||
     * https://datatracker.ietf.org/doc/html/rfc3596
 | 
			
		||||
     */
 | 
			
		||||
    switch(type){
 | 
			
		||||
        case 1:
 | 
			
		||||
           strncpy(tmp, "A", 2);
 | 
			
		||||
@ -197,6 +202,9 @@ static char *mapType(const int type){
 | 
			
		||||
        case 16:
 | 
			
		||||
           strncpy(tmp, "TXT", 4);
 | 
			
		||||
           break;
 | 
			
		||||
        case 28:
 | 
			
		||||
            strncpy(tmp, "AAAA", 5);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
           strncpy(tmp, "Unknown", 8);
 | 
			
		||||
           break;
 | 
			
		||||
@ -204,8 +212,7 @@ static char *mapType(const int type){
 | 
			
		||||
    return tmp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int handle_event(void *ctx, void *data, size_t data_sz){
 | 
			
		||||
    struct event *s_event = (struct event*)data;
 | 
			
		||||
static void print_query(struct event *s_event){
 | 
			
		||||
    char *req_type, *class, *type;
 | 
			
		||||
    printf("%s:%-10d", inet_ntoa(*(struct in_addr*)&s_event->client), s_event->dport);
 | 
			
		||||
    printf("%-5x", s_event->tid);
 | 
			
		||||
@ -224,28 +231,43 @@ int handle_event(void *ctx, void *data, size_t data_sz){
 | 
			
		||||
    printf("%-5s", type);
 | 
			
		||||
    free(type);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
int handle_event(void *ctx, void *data, size_t data_sz){
 | 
			
		||||
    struct event *s_event = (struct event*)data;
 | 
			
		||||
    if (s_event->req_type == REQ_QUERY){
 | 
			
		||||
        print_query(s_event);
 | 
			
		||||
    }
 | 
			
		||||
    if (s_event->req_type == REQ_ANSWER){
 | 
			
		||||
        for (int i = 0; i < s_event->numAns; i++)
 | 
			
		||||
        int pos = 0;
 | 
			
		||||
        for(int i = 0; i < 32; i++)
 | 
			
		||||
            printf("%d ", s_event->buf[i]);
 | 
			
		||||
        printf("\n");
 | 
			
		||||
        for (int i = 0; i < s_event->numAns; i++){
 | 
			
		||||
            print_query(s_event);
 | 
			
		||||
            uint16_t type2 = (s_event->buf[pos++]) + (s_event->buf[pos++] << 8);
 | 
			
		||||
            uint16_t class2 = (s_event->buf[pos++]) + (s_event->buf[pos++] << 8);
 | 
			
		||||
            uint32_t ttl2 = (s_event->buf[pos++]) + (s_event->buf[pos++] << 8) + (s_event->buf[pos++] << 16) + (s_event->buf[pos++] << 24);
 | 
			
		||||
            uint16_t size2 = (s_event->buf[pos++]) + (s_event->buf[pos++] << 8);
 | 
			
		||||
            type2 = ntohs(type2);
 | 
			
		||||
            class2 = ntohs(class2);
 | 
			
		||||
            ttl2 = ntohs(ttl2);
 | 
			
		||||
            if (type2 == 1) {// -> A
 | 
			
		||||
                uint32_t ip = s_event->buf[pos++] + (s_event->buf[pos++] << 8) + (s_event->buf[pos++] << 16) + (s_event->buf[pos++] << 24);
 | 
			
		||||
                //printf("%d %d %d", s_event->ttl, ntohs(ttl2), ntohs(size2)); 
 | 
			
		||||
                printf("%s (%d)%5d", inet_ntoa(*(struct in_addr*)&ip), type2, ttl2);
 | 
			
		||||
            }
 | 
			
		||||
            if (type2 == 28){ // -> AAAA
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            printf("\n");
 | 
			
		||||
            pos += 2;
 | 
			
		||||
            printf("%d\n", pos);
 | 
			
		||||
        }
 | 
			
		||||
        /*for (int i = 0; i < s_event->numAns; i++)
 | 
			
		||||
            printf("%s ", inet_ntoa(*(struct in_addr*)&s_event->ans[i]));
 | 
			
		||||
        printf("%5d", s_event->ttl);
 | 
			
		||||
        printf("%5d", s_event->ttl);*/
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /*printf("IP: %s\n", inet_ntoa(*(struct in_addr*)&s_event->client));
 | 
			
		||||
    printf("dport: %d\n", s_event->dport);
 | 
			
		||||
    printf("sport: %d\n", s_event->sport);
 | 
			
		||||
    printf("Transaction ID: %x\n", s_event->tid);
 | 
			
		||||
    printf("Request type: ");
 | 
			
		||||
    mapReqType(s_event->req_type);
 | 
			
		||||
    printf("qname: %s\n", s_event->qname);
 | 
			
		||||
    printf("Class: ");
 | 
			
		||||
    mapClass(s_event->class);
 | 
			
		||||
    printf("Type: ");
 | 
			
		||||
    mapType(s_event->type);
 | 
			
		||||
 | 
			
		||||
    if (s_event->req_type == REQ_ANSWER)
 | 
			
		||||
        printf("Data: %s\n", inet_ntoa(*(struct in_addr*)&s_event->ans));
 | 
			
		||||
    */
 | 
			
		||||
    printf("\n");
 | 
			
		||||
    
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,7 @@ struct {
 | 
			
		||||
 | 
			
		||||
struct {
 | 
			
		||||
    __uint(type, BPF_MAP_TYPE_HASH);
 | 
			
		||||
    __uint(max_entries, 32768); // pid_max -> https://linux.die.net/man/5/proc
 | 
			
		||||
    __uint(max_entries, 32768); 
 | 
			
		||||
    __type(key, uint16_t);
 | 
			
		||||
    __type(value, struct dns_answer);
 | 
			
		||||
} m_tid SEC(".maps");
 | 
			
		||||
@ -118,16 +118,15 @@ static size_t get_query_section(struct __sk_buff *skb, struct event *s_event, ui
 | 
			
		||||
 | 
			
		||||
    return len;
 | 
			
		||||
}
 | 
			
		||||
static size_t get_answer(struct __sk_buff *skb, struct event *s_event, size_t tlen, int index){
 | 
			
		||||
    size_t len = 0;
 | 
			
		||||
    unsigned char buf[25] = {0}; // Need to be unsigned, otherwise, the result is fffff
 | 
			
		||||
static unsigned int get_answer(struct __sk_buff *skb, struct event *s_event, size_t tlen, unsigned int index){
 | 
			
		||||
    unsigned char buf[2] = {0}; // Need to be unsigned, otherwise, the result is fffff
 | 
			
		||||
    unsigned int offset = index;
 | 
			
		||||
 | 
			
		||||
    // Get the 2 first bytes to identify if it's a message compression or not
 | 
			
		||||
    bpf_printk("offset: %d", tlen);
 | 
			
		||||
    if(bpf_skb_load_bytes(skb, tlen, &buf, 2) < 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    tlen += 2; // Which is for the message compression
 | 
			
		||||
    bpf_printk("tlen: %d", tlen);
 | 
			
		||||
    tlen += 2;
 | 
			
		||||
    /*
 | 
			
		||||
     * According to the RFC 1035 (https://datatracker.ietf.org/doc/html/rfc1035#section-4.1.4)
 | 
			
		||||
     * In the section 4.1.4, message compression, the first two bits are set at 11 (0xc),
 | 
			
		||||
@ -138,8 +137,6 @@ static size_t get_answer(struct __sk_buff *skb, struct event *s_event, size_t tl
 | 
			
		||||
        /*
 | 
			
		||||
         * I cannot read the labels, because the eBPF verifier considerate as a infinity loop
 | 
			
		||||
         */
 | 
			
		||||
        // bpf_printk("new offset: %d", sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + buf[1]);
 | 
			
		||||
        // get_labels2(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + 12, s_event);
 | 
			
		||||
 | 
			
		||||
        /* 
 | 
			
		||||
         * According to the RFC 1035, the structure of answer is like that:
 | 
			
		||||
@ -147,45 +144,54 @@ static size_t get_answer(struct __sk_buff *skb, struct event *s_event, size_t tl
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        // Get the class and type
 | 
			
		||||
        uint16_t type, class;
 | 
			
		||||
        uint32_t ttl;
 | 
			
		||||
        // bpf_printk("offset: %d", tlen);
 | 
			
		||||
        bpf_skb_load_bytes(skb, tlen, &type, sizeof(uint16_t));
 | 
			
		||||
        if ((void*)(offset) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
 | 
			
		||||
            return 0;
 | 
			
		||||
        bpf_printk("offset: %d", offset);
 | 
			
		||||
        bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint16_t));
 | 
			
		||||
        uint16_t type = s_event->buf[0] + (s_event->buf[1] << 8);
 | 
			
		||||
        tlen += 2;
 | 
			
		||||
        // bpf_printk("offset: %d", tlen);
 | 
			
		||||
        bpf_skb_load_bytes(skb, tlen, &class, sizeof(uint16_t));
 | 
			
		||||
        offset += 2;
 | 
			
		||||
 | 
			
		||||
        if ((void*)(offset += 2) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
 | 
			
		||||
            return 0;
 | 
			
		||||
        if(bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint16_t)) < 0)
 | 
			
		||||
            return 0;
 | 
			
		||||
        tlen += 4;
 | 
			
		||||
        // bpf_printk("offset: %d", tlen);
 | 
			
		||||
 | 
			
		||||
        // Get ttl
 | 
			
		||||
        bpf_skb_load_bytes(skb, tlen, &ttl, sizeof(uint32_t));
 | 
			
		||||
        if(bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint32_t)) < 0)
 | 
			
		||||
            return 0;
 | 
			
		||||
        if ((void*)(offset += 4) >= MAX_UDP_PAYLOAD - sizeof(uint32_t))
 | 
			
		||||
            return 0;
 | 
			
		||||
        tlen += 2;
 | 
			
		||||
        // bpf_printk("offset: %d", tlen);
 | 
			
		||||
        s_event->ttl = ntohs(ttl);
 | 
			
		||||
 | 
			
		||||
        // Get data size
 | 
			
		||||
        uint16_t size;
 | 
			
		||||
        bpf_skb_load_bytes(skb, tlen, &size, sizeof(uint16_t));
 | 
			
		||||
        // bpf_printk("size: %d", ntohs(size));
 | 
			
		||||
        bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint16_t));
 | 
			
		||||
        if ((void*)(offset += 2) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
 | 
			
		||||
            return 0;
 | 
			
		||||
        tlen += 2;
 | 
			
		||||
 | 
			
		||||
        // if class is A, we push to an ipv4 map
 | 
			
		||||
 | 
			
		||||
        // if class is AAAA, we push to an ipv6 map
 | 
			
		||||
 | 
			
		||||
        // if class is SOa, we push to an soa map
 | 
			
		||||
 | 
			
		||||
        // etc...
 | 
			
		||||
 | 
			
		||||
        uint32_t data;
 | 
			
		||||
        bpf_skb_load_bytes(skb, tlen, &data, sizeof(uint32_t));
 | 
			
		||||
        s_event->ans[index] = data;
 | 
			
		||||
        if (s_event->type == 1) { // -> A
 | 
			
		||||
            bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint32_t)); 
 | 
			
		||||
        }
 | 
			
		||||
        //offset += ntohs(size);
 | 
			
		||||
        tlen += ntohs(size);
 | 
			
		||||
 | 
			
		||||
        //tlen += 2;
 | 
			
		||||
        //offset += 2; // For the 2 first bytes (message compression)
 | 
			
		||||
        //if ((void*)(offset += ntohs(size)) >= MAX_UDP_PAYLOAD - ntohs(size))
 | 
			
		||||
        //    return 0;
 | 
			
		||||
        //if ((void*)(offset += 2) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
 | 
			
		||||
        //    return 0;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        // get_labels2(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr), s_event);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return len;
 | 
			
		||||
    bpf_printk("tlen: %d", tlen);
 | 
			
		||||
    return offset;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * https://datatracker.ietf.org/doc/html/rfc1035
 | 
			
		||||
@ -320,21 +326,22 @@ static void dnsanswer(struct __sk_buff *skb, struct iphdr ip, struct udphdr udp,
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ntohs(dns.nbAnswerRRs) > 0){
 | 
			
		||||
    if (ans > 0){
 | 
			
		||||
        /*
 | 
			
		||||
         * We get a least the 5 last answer
 | 
			
		||||
         * In the RFC 1035 (https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.4) the max udp payload is 512 bytes
 | 
			
		||||
         * The program limit te size of the answer
 | 
			
		||||
         * The program limit size of the answer
 | 
			
		||||
         */
 | 
			
		||||
        offset += sizeof(struct dnshdr) + query_len; // For the pos in the answer section in the skb
 | 
			
		||||
        uint16_t i;
 | 
			
		||||
        for (i = 0; i < ans; i++){
 | 
			
		||||
            get_answer(skb, s_event, offset, i);
 | 
			
		||||
        unsigned int offset_ans = 0;
 | 
			
		||||
        for (uint16_t i = 0; i < ans; i++){
 | 
			
		||||
            offset_ans = get_answer(skb, s_event, offset, offset_ans);
 | 
			
		||||
            offset += offset_ans;
 | 
			
		||||
            // For eBPF verifier, to be sure we leave the loop
 | 
			
		||||
            if (i == ans || i == 5)
 | 
			
		||||
            if (i == ans || i == 5 || offset_ans >= 512)
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        s_event->numAns = i;
 | 
			
		||||
        s_event->numAns = ans;
 | 
			
		||||
    }
 | 
			
		||||
    if (ntohs(dns.nbAuthorityRRs) > 0){
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								test
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								test
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user