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_QUERY 0x00
|
||||||
#define REQ_ANSWER 0x01
|
#define REQ_ANSWER 0x01
|
||||||
|
|
||||||
|
/* See section 2.3.4 RFC 1035 */
|
||||||
|
#define MAX_UDP_PAYLOAD 512
|
||||||
|
#define MAx_NAME_LEN 255
|
||||||
|
|
||||||
struct dnshdr {
|
struct dnshdr {
|
||||||
uint16_t transactionID;
|
uint16_t transactionID;
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
@ -15,12 +19,6 @@ struct dnshdr {
|
|||||||
uint16_t nbAdditionalRRs;
|
uint16_t nbAdditionalRRs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*struct dns_query {
|
|
||||||
char *name;
|
|
||||||
uint16_t type;
|
|
||||||
uint16_t class;
|
|
||||||
};*/
|
|
||||||
|
|
||||||
struct event {
|
struct event {
|
||||||
uint32_t client;
|
uint32_t client;
|
||||||
int dport;
|
int dport;
|
||||||
@ -30,9 +28,8 @@ struct event {
|
|||||||
char qname[QNAME_SIZE];
|
char qname[QNAME_SIZE];
|
||||||
uint16_t class;
|
uint16_t class;
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint32_t ans[5];
|
|
||||||
uint16_t numAns;
|
uint16_t numAns;
|
||||||
uint32_t ttl;
|
unsigned char buf[MAX_UDP_PAYLOAD]; // On stocke la data au format size + data
|
||||||
};
|
};
|
||||||
|
|
||||||
struct query_section{
|
struct query_section{
|
||||||
@ -43,9 +40,10 @@ struct query_section{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct dns_answer {
|
struct dns_answer {
|
||||||
char qname[QNAME_SIZE];
|
char data[512];
|
||||||
char ip[32];
|
uint16_t class;
|
||||||
int ttl;
|
uint16_t type;
|
||||||
|
uint32_t ttl;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -148,6 +148,11 @@ static char *mapType(const int type){
|
|||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
return 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){
|
switch(type){
|
||||||
case 1:
|
case 1:
|
||||||
strncpy(tmp, "A", 2);
|
strncpy(tmp, "A", 2);
|
||||||
@ -197,6 +202,9 @@ static char *mapType(const int type){
|
|||||||
case 16:
|
case 16:
|
||||||
strncpy(tmp, "TXT", 4);
|
strncpy(tmp, "TXT", 4);
|
||||||
break;
|
break;
|
||||||
|
case 28:
|
||||||
|
strncpy(tmp, "AAAA", 5);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
strncpy(tmp, "Unknown", 8);
|
strncpy(tmp, "Unknown", 8);
|
||||||
break;
|
break;
|
||||||
@ -204,8 +212,7 @@ static char *mapType(const int type){
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_event(void *ctx, void *data, size_t data_sz){
|
static void print_query(struct event *s_event){
|
||||||
struct event *s_event = (struct event*)data;
|
|
||||||
char *req_type, *class, *type;
|
char *req_type, *class, *type;
|
||||||
printf("%s:%-10d", inet_ntoa(*(struct in_addr*)&s_event->client), s_event->dport);
|
printf("%s:%-10d", inet_ntoa(*(struct in_addr*)&s_event->client), s_event->dport);
|
||||||
printf("%-5x", s_event->tid);
|
printf("%-5x", s_event->tid);
|
||||||
@ -224,28 +231,43 @@ int handle_event(void *ctx, void *data, size_t data_sz){
|
|||||||
printf("%-5s", type);
|
printf("%-5s", type);
|
||||||
free(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){
|
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("%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");
|
printf("\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -31,7 +31,7 @@ struct {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
__uint(type, BPF_MAP_TYPE_HASH);
|
__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(key, uint16_t);
|
||||||
__type(value, struct dns_answer);
|
__type(value, struct dns_answer);
|
||||||
} m_tid SEC(".maps");
|
} 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;
|
return len;
|
||||||
}
|
}
|
||||||
static size_t get_answer(struct __sk_buff *skb, struct event *s_event, size_t tlen, int index){
|
static unsigned int get_answer(struct __sk_buff *skb, struct event *s_event, size_t tlen, unsigned int index){
|
||||||
size_t len = 0;
|
unsigned char buf[2] = {0}; // Need to be unsigned, otherwise, the result is fffff
|
||||||
unsigned char buf[25] = {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
|
// 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)
|
if(bpf_skb_load_bytes(skb, tlen, &buf, 2) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
bpf_printk("tlen: %d", tlen);
|
||||||
tlen += 2; // Which is for the message compression
|
tlen += 2;
|
||||||
/*
|
/*
|
||||||
* According to the RFC 1035 (https://datatracker.ietf.org/doc/html/rfc1035#section-4.1.4)
|
* 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),
|
* 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
|
* 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:
|
* 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
|
// Get the class and type
|
||||||
uint16_t type, class;
|
if ((void*)(offset) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
|
||||||
uint32_t ttl;
|
return 0;
|
||||||
// bpf_printk("offset: %d", tlen);
|
bpf_printk("offset: %d", offset);
|
||||||
bpf_skb_load_bytes(skb, tlen, &type, sizeof(uint16_t));
|
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;
|
tlen += 2;
|
||||||
// bpf_printk("offset: %d", tlen);
|
offset += 2;
|
||||||
bpf_skb_load_bytes(skb, tlen, &class, sizeof(uint16_t));
|
|
||||||
|
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;
|
tlen += 4;
|
||||||
// bpf_printk("offset: %d", tlen);
|
|
||||||
// Get ttl
|
// 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;
|
tlen += 2;
|
||||||
// bpf_printk("offset: %d", tlen);
|
|
||||||
s_event->ttl = ntohs(ttl);
|
|
||||||
|
|
||||||
// Get data size
|
// Get data size
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
bpf_skb_load_bytes(skb, tlen, &size, sizeof(uint16_t));
|
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;
|
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;
|
uint32_t data;
|
||||||
bpf_skb_load_bytes(skb, tlen, &data, sizeof(uint32_t));
|
if (s_event->type == 1) { // -> A
|
||||||
s_event->ans[index] = data;
|
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 {
|
else {
|
||||||
// get_labels2(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr), s_event);
|
// get_labels2(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr), s_event);
|
||||||
}
|
}
|
||||||
|
bpf_printk("tlen: %d", tlen);
|
||||||
return len;
|
return offset;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* https://datatracker.ietf.org/doc/html/rfc1035
|
* 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntohs(dns.nbAnswerRRs) > 0){
|
if (ans > 0){
|
||||||
/*
|
/*
|
||||||
* We get a least the 5 last answer
|
* 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
|
* 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
|
offset += sizeof(struct dnshdr) + query_len; // For the pos in the answer section in the skb
|
||||||
uint16_t i;
|
unsigned int offset_ans = 0;
|
||||||
for (i = 0; i < ans; i++){
|
for (uint16_t i = 0; i < ans; i++){
|
||||||
get_answer(skb, s_event, offset, i);
|
offset_ans = get_answer(skb, s_event, offset, offset_ans);
|
||||||
|
offset += offset_ans;
|
||||||
// For eBPF verifier, to be sure we leave the loop
|
// For eBPF verifier, to be sure we leave the loop
|
||||||
if (i == ans || i == 5)
|
if (i == ans || i == 5 || offset_ans >= 512)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s_event->numAns = i;
|
s_event->numAns = ans;
|
||||||
}
|
}
|
||||||
if (ntohs(dns.nbAuthorityRRs) > 0){
|
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