update
This commit is contained in:
parent
65a0f2447d
commit
8e9822d232
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,2 @@
|
|||||||
src/**.swp
|
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
|
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
|
#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';
|
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
|
* This function save to rsyslog format the answer section
|
||||||
*/
|
*/
|
||||||
static void answer_to_log(struct event *s_event){
|
static void answer_to_log(struct event *s_event){
|
||||||
|
int pos = 0;
|
||||||
for (int i = 0; i < s_event->numAns; i++){
|
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);
|
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);
|
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("%5s:%5d\t", inet_ntoa(*(struct in_addr*)&s_event->client), s_event->dport);
|
||||||
printf("%x\t", s_event->tid);
|
printf("%x\t", s_event->tid);
|
||||||
|
|
||||||
type = s_event->buf[pos++];
|
get_answer(s_event, &class, &type, &size, &ttl, &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;
|
|
||||||
|
|
||||||
type = ntohs(type);
|
type = ntohs(type);
|
||||||
class = ntohs(class);
|
class = ntohs(class);
|
||||||
|
@ -16,14 +16,6 @@
|
|||||||
#include "common.h"
|
#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 {
|
struct {
|
||||||
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
||||||
__uint(max_entries, 256 * 1024 /* 256kb */);
|
__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';
|
s_event->qname[qname_len - 1] = '\0';
|
||||||
qname_len++;
|
qname_len++;
|
||||||
// dquery->qname_len = qname_len;
|
|
||||||
// bpf_printk("qname: %s", s_event->qname);
|
|
||||||
// bpf_printk("qname len: %d", qname_len);
|
// bpf_printk("qname len: %d", qname_len);
|
||||||
return 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;
|
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
|
* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dnsanswer_old(struct __sk_buff *skb, struct iphdr ip, struct udphdr udp, int dport, int sport){
|
/*
|
||||||
//__u16 udplen = 0U;
|
* This function read the dns answer section
|
||||||
|
* All the answer is store in the buf variable and handle in the user space
|
||||||
// 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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void dnsanswer(struct __sk_buff *skb, struct iphdr ip, struct udphdr udp, int dport, int sport){
|
static void dnsanswer(struct __sk_buff *skb, struct iphdr ip, struct udphdr udp, int dport, int sport){
|
||||||
struct event *s_event;
|
struct event *s_event;
|
||||||
struct dnshdr dns;
|
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
|
* otherwise, I have an issue with the eBPF verifier
|
||||||
*/
|
*/
|
||||||
offset += sizeof(struct dnshdr) + query_len;
|
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);
|
bpf_skb_load_bytes(skb, offset + index, s_event->buf + index, 1);
|
||||||
// index++;
|
|
||||||
}
|
|
||||||
bpf_ringbuf_submit(s_event, 0);
|
bpf_ringbuf_submit(s_event, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user