From b57efa5cad09bd785fded63619507bb6637c846b Mon Sep 17 00:00:00 2001 From: geoffrey Date: Tue, 28 Jan 2025 20:27:03 +0100 Subject: [PATCH] Update project --- dns-trace | Bin 18704 -> 18816 bytes src/common.h | 20 +++++----- src/dns-trace.c | 62 +++++++++++++++++++++---------- src/dns-trace.ebpf.c | 85 +++++++++++++++++++++++-------------------- src/dns-trace.ebpf.o | Bin 34440 -> 37000 bytes test | Bin 16608 -> 16608 bytes 6 files changed, 97 insertions(+), 70 deletions(-) diff --git a/dns-trace b/dns-trace index 52e97db7c1c2d1352416e71f897529211bddc794..46ae51c4be6729c9799c808d3f9601bd65f82a47 100755 GIT binary patch delta 5159 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 diff --git a/src/common.h b/src/common.h index 147b458..34ebbf3 100644 --- a/src/common.h +++ b/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 diff --git a/src/dns-trace.c b/src/dns-trace.c index 786f1e9..4566159 100644 --- a/src/dns-trace.c +++ b/src/dns-trace.c @@ -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; diff --git a/src/dns-trace.ebpf.c b/src/dns-trace.ebpf.c index 1dc72cd..91000e9 100644 --- a/src/dns-trace.ebpf.c +++ b/src/dns-trace.ebpf.c @@ -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){ diff --git a/src/dns-trace.ebpf.o b/src/dns-trace.ebpf.o index c242db0f5e3016b20a097fb75a1bdd308dee4259..e6bf9dbc0827d6877b2e6e809b6a6540c9dc8f19 100644 GIT binary patch literal 37000 zcmd^odwf;Znf5x@+&KplARx--9&RDw8o3#)C{o0LAfUDDq88Buog2-w7WXt`LRq_UU>_){DuI9GI>60~1yJ zEHck(5n}J;*DjJn+}gU*Yo2^T;!5E5rrl|#wP(G~!;{Y|xgv6e$UgeI!~-W3E`a>` zix)3G8x|q~*0T{ImLq;At~joN$8kd_0H1OLcPLDG$~_wuvObibjO+02XQloEWUc_d zFOC2Yyi3WA50y(|d}yqU z2i~vv1+Z%c$UwUtdyRbqN}bq&dj1>ov%UkUFEJ}LFiz=beOb?iOJ9-oq#vq*W8%jW zn|c^KO+DByCP3{)V{bz1{VMc$5IFcT<-dU@C7qb2VwS^@okp+1o_l2^Myu~HsNb{` z>}6KdKA980kaoTddy?Sqo$!cMM897ND#&l9Jl21>KGnXyzK5i~uj+OyKpdmqe#sUO zt4It?Pz3ug!`{g+OS_sUpONw5$wL}HukoOcPwV)UjGMHd=%0DevvAxxsn4#*5dC4v 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 literal 34440 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 gCb#|XT6tYa# zFn!l&ulD~hHvhMuvUu|grYc^}E}&T+y}Zgyo3jOWGu9t(&G`TSza-EMk6tj-qto?6 zH<;CV%%j(KA1?#L4v-Bm?)?4#-=o|0g9liA6SPhf_Ydv|GU*3Vi zG2Exu)?b@}!7cc@n=*TC~#^lV)#vH`R!_L9r0u-tN;t7*~ zD!4PQ*zBk{pJ(z5T?@u9n-%qzGc$gfe9};#QDE{zLs4cShJek2M#mW$LnhxeE(Zz* znz%E5m^{-Y9;oc6$#TXClNXw%Gles5<}&-n#<*}Yqpd#Y7a^eOK=5U!uZ z)GZs{|NqYclz{;mAR`8dV}U0800}zs3A8ae^Rh90=3xgabO8$00I|hnMn!kl0HFDd zn;C@{^GtrBYr!~Wv!dQ|X2vO#Pa5hoa!h_`D9S9v;IUcI=r|*z&*YoN