update
This commit is contained in:
parent
65a0f2447d
commit
8e9822d232
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
src/**.swp
|
||||
src/**.log
|
||||
**.log
|
||||
|
BIN
dns-trace
BIN
dns-trace
Binary file not shown.
@ -1,30 +0,0 @@
|
||||
Feb 08 16:03:16 pc-geoffrey dns-trace: <info> Query;tid=68;192.168.1.37:53;class=IN;type=AAAA;
|
||||
Feb 08 16:03:16 pc-geoffrey dns-trace: <info> Answer;tid=68;
|
||||
Feb 08 16:03:23 pc-geoffrey dns-trace: <info> Query;tid=2da6;192.168.1.37:53;class=IN;type=AAAA;
|
||||
Feb 08 16:03:23 pc-geoffrey dns-trace: <info> Answer;tid=2da6;
|
||||
Feb 08 16:17:34 pc-geoffrey dns-trace: <info> Query;tid=4f3a;192.168.1.37:53;class=IN;type=A;
|
||||
Feb 08 16:17:34 pc-geoffrey dns-trace: <info> Query;tid=af42;192.168.1.37:53;class=IN;type=AAAA;
|
||||
Feb 08 16:17:34 pc-geoffrey dns-trace: <info> Answer;tid=4f3a;
|
||||
Feb 08 16:18:25 pc-geoffrey dns-trace: <info> Query;tid=e29b;192.168.1.37:53;class=IN;type=A;
|
||||
Feb 08 16:18:25 pc-geoffrey dns-trace: <info> Answer;tid=e29b;192.168.1.37:45247;
|
||||
Feb 08 16:19:52 pc-geoffrey dns-trace: <info> Query;tid=a9ff;192.168.1.37:53;class=IN;type=AAAA;
|
||||
Feb 08 16:19:52 pc-geoffrey dns-trace: <info> Answer;tid=a9ff;192.168.1.37:40040;
|
||||
Feb 08 16:19:52 pc-geoffrey dns-trace: <info> Answer;tid=a9ff;192.168.1.37:40040;
|
||||
Feb 08 16:19:52 pc-geoffrey dns-trace: <info> Answer;tid=a9ff;192.168.1.37:40040;
|
||||
Feb 08 16:21:16 pc-geoffrey dns-trace: <info> Query;tid=b7c2;192.168.1.37:53;class=IN;type=AAAA;www.fortinet.com;
|
||||
Feb 08 16:21:16 pc-geoffrey dns-trace: <info> Answer;tid=b7c2;192.168.1.37:51591;
|
||||
Feb 08 16:21:16 pc-geoffrey dns-trace: <info> Answer;tid=b7c2;192.168.1.37:51591;
|
||||
Feb 08 16:21:16 pc-geoffrey dns-trace: <info> Answer;tid=b7c2;192.168.1.37:51591;
|
||||
Feb 08 16:21:44 pc-geoffrey dns-trace: <info> Query;tid=9f64;192.168.1.37:53;class=IN;type=A;domain=safebrowsing.googleapis.com;
|
||||
Feb 08 16:21:44 pc-geoffrey dns-trace: <info> Answer;tid=9f64;192.168.1.37:52355;
|
||||
Feb 08 16:21:44 pc-geoffrey dns-trace: <info> Query;tid=473f;192.168.1.37:53;class=IN;type=AAAA;domain=www.fortinet.com;
|
||||
Feb 08 16:21:44 pc-geoffrey dns-trace: <info> Answer;tid=473f;192.168.1.37:59032;
|
||||
Feb 08 16:21:44 pc-geoffrey dns-trace: <info> Answer;tid=473f;192.168.1.37:59032;
|
||||
Feb 08 16:21:44 pc-geoffrey dns-trace: <info> Answer;tid=473f;192.168.1.37:59032;
|
||||
Feb 08 16:21:51 pc-geoffrey dns-trace: <info> Query;tid=22c8;192.168.1.37:53;class=IN;type=AAAA;domain=www.fortinet.com;
|
||||
Feb 08 16:21:51 pc-geoffrey dns-trace: <info> Answer;tid=22c8;192.168.1.37:40059;
|
||||
Feb 08 16:21:51 pc-geoffrey dns-trace: <info> Answer;tid=22c8;192.168.1.37:40059;
|
||||
Feb 08 16:21:51 pc-geoffrey dns-trace: <info> Answer;tid=22c8;192.168.1.37:40059;
|
||||
Feb 08 16:21:52 pc-geoffrey dns-trace: <info> Query;tid=57f3;192.168.1.37:53;class=IN;type=A;domain=www.bucchino.org;
|
||||
Feb 08 16:21:52 pc-geoffrey dns-trace: <info> Answer;tid=57f3;192.168.1.37:53594;
|
||||
Feb 08 16:21:52 pc-geoffrey dns-trace: <info> Answer;tid=57f3;192.168.1.37:53594;
|
14
src/common.h
14
src/common.h
@ -32,18 +32,4 @@ struct event {
|
||||
unsigned char buf[MAX_UDP_PAYLOAD]; // On stocke la data au format size + data
|
||||
};
|
||||
|
||||
/*struct query_section{
|
||||
char qname[QNAME_SIZE];
|
||||
size_t qname_len;
|
||||
uint16_t class;
|
||||
uint16_t type;
|
||||
};*/
|
||||
|
||||
/*struct dns_answer {
|
||||
char data[512];
|
||||
uint16_t class;
|
||||
uint16_t type;
|
||||
uint32_t ttl;
|
||||
};*/
|
||||
|
||||
#endif
|
||||
|
100
src/dns-trace.c
100
src/dns-trace.c
@ -353,13 +353,99 @@ static void get_labels(unsigned char *buf, char *qname){
|
||||
}
|
||||
qname[pos - 1] = '\0';
|
||||
}
|
||||
/*
|
||||
* This function read the event buf which contains the DNS answer section
|
||||
*/
|
||||
static void get_answer(struct event *s_event, uint16_t *class, uint16_t *type, uint16_t *size, uint32_t *ttl, int *pos){
|
||||
int p = *pos;
|
||||
|
||||
*type = s_event->buf[p++];
|
||||
*type |= s_event->buf[p++] << 8;
|
||||
|
||||
*class = s_event->buf[p++];
|
||||
*class |= s_event->buf[p++] << 8;
|
||||
|
||||
*ttl = s_event->buf[p++];
|
||||
*ttl |= s_event->buf[p++] << 8;
|
||||
*ttl |= s_event->buf[p++] << 16;
|
||||
*ttl |= s_event->buf[p++] << 24;
|
||||
|
||||
*size = s_event->buf[p++];
|
||||
*size |= s_event->buf[p++] << 8;
|
||||
|
||||
*pos = p;
|
||||
}
|
||||
/*
|
||||
* This function save to rsyslog format the answer section
|
||||
*/
|
||||
static void answer_to_log(struct event *s_event){
|
||||
int pos = 0;
|
||||
for (int i = 0; i < s_event->numAns; i++){
|
||||
char *s_class, *s_type;
|
||||
uint16_t i_type, i_class, i_size;
|
||||
uint32_t i_ttl;
|
||||
char b_class[16], b_type[16], b_ttl[16];
|
||||
/*
|
||||
* 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),
|
||||
* that's means, it's a pointer.
|
||||
* For instance, the two bytes 0xc00c, 0xc (11) it's the pointer and 0x00c is the position in the DNS header
|
||||
*/
|
||||
uint16_t msg = s_event->buf[pos++];
|
||||
msg |= s_event->buf[pos++] << 8;
|
||||
|
||||
header_to_log(s_event);
|
||||
|
||||
get_answer(s_event, &i_class, &i_type, &i_size, &i_ttl, &pos);
|
||||
|
||||
i_type = ntohs(i_type);
|
||||
i_class = ntohs(i_class);
|
||||
i_ttl = ntohl(i_ttl);
|
||||
i_size = ntohs(i_size);
|
||||
|
||||
s_class = mapClass(i_class);
|
||||
snprintf(b_class, 16, "class=%s;", s_class);
|
||||
fwrite(b_class, strlen(b_class), 1, f);
|
||||
free(s_class);
|
||||
|
||||
s_type = mapType(i_type);
|
||||
snprintf(b_type, 16, "type=%s;", s_type);
|
||||
fwrite(b_type, strlen(b_type), 1, f);
|
||||
free(s_type);
|
||||
|
||||
snprintf(b_ttl, 16, "ttl=%d;", i_ttl);
|
||||
fwrite(b_ttl, strlen(b_ttl), 1, f);
|
||||
|
||||
// Decode data
|
||||
if (i_type == 1) { // -> A
|
||||
uint32_t ip = s_event->buf[pos] + (s_event->buf[pos+1] << 8) + (s_event->buf[pos+2] << 16) + (s_event->buf[pos+3] << 24);
|
||||
char s_ip[36];
|
||||
snprintf(s_ip, 36, "ip=%s;", inet_ntoa(*(struct in_addr*)&ip));
|
||||
fwrite(s_ip, strlen(s_ip), 1, f);
|
||||
}
|
||||
if (i_type == 5) { // -> CNAME
|
||||
char cname[i_size];
|
||||
char buf[i_size + 7]; // 7 -> cname=;
|
||||
get_labels(s_event->buf + pos, cname);
|
||||
snprintf(buf, i_size + 7, "cname=%s;", cname);
|
||||
fwrite(buf, strlen(buf), 1, f);
|
||||
}
|
||||
if (i_type == 28){ // -> AAAA
|
||||
char buf[128];
|
||||
snprintf(buf, 128, "ipv6=%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x;",
|
||||
s_event->buf[pos], s_event->buf[pos + 1],
|
||||
s_event->buf[pos + 2], s_event->buf[pos + 3],
|
||||
s_event->buf[pos + 4], s_event->buf[pos + 5],
|
||||
s_event->buf[pos + 6], s_event->buf[pos + 7],
|
||||
s_event->buf[pos + 8], s_event->buf[pos + 9],
|
||||
s_event->buf[pos + 10], s_event->buf[pos + 11],
|
||||
s_event->buf[pos + 12], s_event->buf[pos + 13],
|
||||
s_event->buf[pos + 14], s_event->buf[pos + 15]);
|
||||
fwrite(buf, strlen(buf), 1, f);
|
||||
}
|
||||
|
||||
pos += i_size;
|
||||
|
||||
fwrite("\n", 1, 1, f);
|
||||
}
|
||||
}
|
||||
@ -390,19 +476,7 @@ static void print_answer(struct event *s_event){
|
||||
printf("%5s:%5d\t", inet_ntoa(*(struct in_addr*)&s_event->client), s_event->dport);
|
||||
printf("%x\t", s_event->tid);
|
||||
|
||||
type = s_event->buf[pos++];
|
||||
type |= s_event->buf[pos++] << 8;
|
||||
|
||||
class = s_event->buf[pos++];
|
||||
class |= s_event->buf[pos++] << 8;
|
||||
|
||||
ttl = s_event->buf[pos++];
|
||||
ttl |= s_event->buf[pos++] << 8;
|
||||
ttl |= s_event->buf[pos++] << 16;
|
||||
ttl |= s_event->buf[pos++] << 24;
|
||||
|
||||
size = s_event->buf[pos++];
|
||||
size |= s_event->buf[pos++] << 8;
|
||||
get_answer(s_event, &class, &type, &size, &ttl, &pos);
|
||||
|
||||
type = ntohs(type);
|
||||
class = ntohs(class);
|
||||
|
@ -16,14 +16,6 @@
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/*
|
||||
* Helper:
|
||||
* Issue: invalid indirect read from stack R2 off
|
||||
* Fix: check if all variables is initialised
|
||||
* Issue: R1 invalid mem access 'inv'
|
||||
* Fix: the value can be NULL
|
||||
*/
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
||||
__uint(max_entries, 256 * 1024 /* 256kb */);
|
||||
@ -59,8 +51,6 @@ static size_t get_labels(struct __sk_buff *skb, size_t offset, struct event *s_e
|
||||
}
|
||||
s_event->qname[qname_len - 1] = '\0';
|
||||
qname_len++;
|
||||
// dquery->qname_len = qname_len;
|
||||
// bpf_printk("qname: %s", s_event->qname);
|
||||
// bpf_printk("qname len: %d", qname_len);
|
||||
return qname_len;
|
||||
}
|
||||
@ -87,77 +77,6 @@ static size_t get_query_section(struct __sk_buff *skb, struct event *s_event, ui
|
||||
|
||||
return len;
|
||||
}
|
||||
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
|
||||
if(bpf_skb_load_bytes(skb, tlen, &buf, 2) < 0)
|
||||
return 0;
|
||||
tlen += 2; // For the message compression
|
||||
|
||||
/*
|
||||
* 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),
|
||||
* that's means, it's a pointer.
|
||||
* For instance, the two bytes 0xc00c, 0xc (11) it's the pointer and 0x00c is the position in the DNS header
|
||||
*/
|
||||
if (buf[0] == 0xc0){
|
||||
/*
|
||||
* I cannot read the labels, because the eBPF verifier considerate as a infinity loop
|
||||
*/
|
||||
|
||||
/*
|
||||
* According to the RFC 1035, the structure of answer is like that:
|
||||
* https://datatracker.ietf.org/doc/html/rfc1035#section-4.1.3
|
||||
*/
|
||||
|
||||
// Get the class and type
|
||||
if ((offset) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
|
||||
return 0;
|
||||
|
||||
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;
|
||||
if ((offset += 2) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
|
||||
return 0;
|
||||
//offset += 2;
|
||||
|
||||
// For class
|
||||
if(bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint16_t)) < 0)
|
||||
return 0;
|
||||
tlen += 2;
|
||||
if ((offset += 2) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
|
||||
return 0;
|
||||
|
||||
// Get ttl
|
||||
if(bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint32_t)) < 0)
|
||||
return 0;
|
||||
if ((offset += 4) >= MAX_UDP_PAYLOAD - sizeof(uint32_t))
|
||||
return 0;
|
||||
tlen += 4;
|
||||
|
||||
// Get data size
|
||||
uint16_t size;
|
||||
bpf_skb_load_bytes(skb, tlen, &size, sizeof(uint16_t));
|
||||
bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint16_t));
|
||||
if ((offset += 2) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
|
||||
return 0;
|
||||
tlen += 2;
|
||||
|
||||
if (s_event->type == 1) { // -> A
|
||||
bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint32_t));
|
||||
}
|
||||
if ((offset += ntohs(size)) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
|
||||
return 0;
|
||||
tlen += ntohs(size);
|
||||
}
|
||||
else {
|
||||
// get_labels(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr), s_event);
|
||||
}
|
||||
bpf_printk("End offset: %d", offset);
|
||||
return offset;
|
||||
}
|
||||
/*
|
||||
* https://datatracker.ietf.org/doc/html/rfc1035
|
||||
*/
|
||||
@ -202,46 +121,10 @@ static int dnsquery(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip, s
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dnsanswer_old(struct __sk_buff *skb, struct iphdr ip, struct udphdr udp, int dport, int sport){
|
||||
//__u16 udplen = 0U;
|
||||
|
||||
// Check with ip.len
|
||||
//const __u32 tot_len = ntohs(ip.tot_len);
|
||||
// __u32 payload_len = (ntohs(ip.tot_len) - sizeof(struct iphdr) - sizeof(struct udphdr));
|
||||
__u32 payload_len = (ntohs(ip.tot_len) - sizeof(struct iphdr) - sizeof(struct udphdr)) & 0xff;
|
||||
|
||||
if (payload_len > skb->len)
|
||||
return;
|
||||
|
||||
bpf_printk("payload len %d", payload_len);
|
||||
if (payload_len <= -1) {
|
||||
bpf_printk("payload len %d", payload_len);
|
||||
}
|
||||
|
||||
// Get udp len
|
||||
//udplen = ntohs(udp.len);
|
||||
|
||||
//bpf_printk("udp len: %d", udplen);
|
||||
|
||||
//if (udplen <= 0)
|
||||
// return 0;
|
||||
|
||||
/*if (offset + udplen > skb->len) {
|
||||
bpf_printk("outbound");
|
||||
plen = sizeof(struct dnshdr);
|
||||
}*/
|
||||
/*long err = bpf_skb_load_bytes(skb, offset, &buf, payload_len);
|
||||
if(err < 0){
|
||||
bpf_printk("failed");
|
||||
// bpf_ringbuf_discard(s_event, 0);
|
||||
return;
|
||||
}*/
|
||||
// Cast to dnshdr
|
||||
// dns = (struct dnshdr*)buf;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function read the dns answer section
|
||||
* All the answer is store in the buf variable and handle in the user space
|
||||
*/
|
||||
static void dnsanswer(struct __sk_buff *skb, struct iphdr ip, struct udphdr udp, int dport, int sport){
|
||||
struct event *s_event;
|
||||
struct dnshdr dns;
|
||||
@ -297,11 +180,9 @@ static void dnsanswer(struct __sk_buff *skb, struct iphdr ip, struct udphdr udp,
|
||||
* otherwise, I have an issue with the eBPF verifier
|
||||
*/
|
||||
offset += sizeof(struct dnshdr) + query_len;
|
||||
//while (index < tlen){
|
||||
for (index = 0; index < tlen || index == MAX_UDP_PAYLOAD; index++) {
|
||||
for (index = 0; index < tlen || index == MAX_UDP_PAYLOAD; index++)
|
||||
bpf_skb_load_bytes(skb, offset + index, s_event->buf + index, 1);
|
||||
// index++;
|
||||
}
|
||||
|
||||
bpf_ringbuf_submit(s_event, 0);
|
||||
}
|
||||
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user