This commit is contained in:
2025-02-08 15:04:30 +01:00
parent 1449cc961d
commit be9022d0a6
17 changed files with 205 additions and 92 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ LIBS=-L../libbpf/src -l:libbpf.a -lelf -lz
all: dns-trace.ebpf.o dns-trace all: dns-trace.ebpf.o dns-trace
dns-trace.ebpf.o: src/dns-trace.ebpf.c dns-trace.ebpf.o: src/dns-trace.ebpf.c
$(CL) -Wall -g -O2 -target bpf -D __TARGET_ARCH_x86_64 -D __BPF_TRACING__ -L../libbpf/src -l:libbpf.a -c src/dns-trace.ebpf.c -o src/dns-trace.ebpf.o $(CL) -Wall -g -O2 -target bpf -D __TARGET_ARCH_x86_64 -D __BPF_TRACING__ -c src/dns-trace.ebpf.c -o src/dns-trace.ebpf.o
dns-trace: src/dns-trace.c dns-trace: src/dns-trace.c
$(GCC) $(CFLAGS) src/dns-trace.c -o dns-trace $(LIBS) $(GCC) $(CFLAGS) src/dns-trace.c -o dns-trace $(LIBS)
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+18
View File
@@ -0,0 +1,18 @@
Feb 08 13:24:15 pc-geoffrey dns-trace: <info> Query;tid=671c;192.168.1.37:53;class=IN;type=AAAA;
Feb 08 13:24:16 pc-geoffrey dns-trace: <info> Query;tid=c537;192.168.1.37:53;class=IN;type=A;
Feb 08 13:24:17 pc-geoffrey dns-trace: <info> Query;tid=12ba;192.168.1.37:53;class=IN;type=A;
Feb 08 14:17:10 pc-geoffrey dns-trace: <info> Query;tid=fa8f;192.168.1.37:53;class=IN;type=A;
Feb 08 14:17:20 pc-geoffrey dns-trace: <info> Query;tid=a417;192.168.1.37:53;class=IN;type=A;
Feb 08 14:21:36 pc-geoffrey dns-trace: <info> Query;tid=34f;192.168.1.37:53;class=IN;type=A;
Feb 08 14:23:23 pc-geoffrey dns-trace: <info> Query;tid=23c8;192.168.1.37:53;class=IN;type=A;
Feb 08 14:25:11 pc-geoffrey dns-trace: <info> Query;tid=e74;192.168.1.37:53;class=IN;type=A;
Feb 08 14:25:21 pc-geoffrey dns-trace: <info> Query;tid=3844;192.168.1.37:53;class=IN;type=A;
Feb 08 14:25:28 pc-geoffrey dns-trace: <info> Query;tid=de58;192.168.1.37:53;class=IN;type=A;
Feb 08 14:27:39 pc-geoffrey dns-trace: <info> Query;tid=4600;192.168.1.37:53;class=IN;type=A;
Feb 08 14:28:04 pc-geoffrey dns-trace: <info> Query;tid=1f5a;192.168.1.37:53;class=IN;type=A;
Feb 08 14:29:20 pc-geoffrey dns-trace: <info> Query;tid=3cc6;192.168.1.37:53;class=IN;type=A;
Feb 08 14:35:12 pc-geoffrey dns-trace: <info> Query;tid=a8d2;192.168.1.37:53;class=IN;type=A;
Feb 08 14:35:12 pc-geoffrey dns-trace: <info> Query;tid=e7ae;192.168.1.37:53;class=IN;type=AAAA;
Feb 08 14:35:16 pc-geoffrey dns-trace: <info> Query;tid=ed16;192.168.1.37:53;class=IN;type=A;
Feb 08 14:35:31 pc-geoffrey dns-trace: <info> Query;tid=28a6;192.168.1.37:53;class=IN;type=A;
Feb 08 14:50:39 pc-geoffrey dns-trace: <info> Query;tid=b19f;192.168.1.37:53;class=IN;type=AAAA;
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -3,4 +3,4 @@
#sudo bpftool btf dump file /sys/kernel/btf/vmlinux format c > src/vmlinux.h #sudo bpftool btf dump file /sys/kernel/btf/vmlinux format c > src/vmlinux.h
make clean make clean
make all && sudo ./dns-trace -i enx98e743c667fc make all && sudo ./dns-trace -i wlp0s20f3 -f dns-trace_`$(echo date '+%F')`.log
BIN
View File
Binary file not shown.
Binary file not shown.
+151 -41
View File
@@ -9,6 +9,7 @@
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
#include <unistd.h> #include <unistd.h>
#include <time.h>
#include <fcntl.h> #include <fcntl.h>
#include <net/if.h> /* if_nametoindex */ #include <net/if.h> /* if_nametoindex */
#include <linux/if_ether.h> #include <linux/if_ether.h>
@@ -17,8 +18,12 @@
#include "common.h" #include "common.h"
/* Global variables */
static struct arguments arguments; static struct arguments arguments;
static int running = 1; static int running = 1;
static FILE *f;
static char hostname[127];
struct arguments { struct arguments {
char *interface; char *interface;
@@ -216,13 +221,38 @@ static char *mapType(const int type){
return tmp; return tmp;
} }
/*
* This function get the localtime into the rsyslog format
*/
static int syslog_time(time_t ts, char t[32], size_t l){
const char format[] = "%b %d %T";
struct tm *lt = localtime(&ts);
if(strftime(t, l, format, lt) == 0)
return -1;
return 0;
}
static void get_hostname(){
/* Get the hostname */
if (gethostname(hostname, 127) == -1){
printf("Failed to get the hostname\n");
strncpy(hostname, "ubuntu", 7);
}
}
/*
* This function print to the stdout the query section
*/
static void print_query(struct event *s_event){ static void print_query(struct event *s_event){
char *req_type, *class, *type; char *req_type, *class, *type;
char t[32];
time_t ts = time(NULL);
syslog_time(ts, t, sizeof(t));
printf("%-20s", t);
req_type = mapReqType(s_event->req_type); req_type = mapReqType(s_event->req_type);
printf("%s ", req_type); printf("%s ", req_type);
free(req_type); free(req_type);
printf("%5s:%d\t\t", inet_ntoa(*(struct in_addr*)&s_event->client), s_event->dport); printf("%5s:%d\t", inet_ntoa(*(struct in_addr*)&s_event->client), s_event->dport);
printf("%x\t", s_event->tid); printf("%x\t", s_event->tid);
class = mapClass(s_event->class); class = mapClass(s_event->class);
@@ -235,6 +265,53 @@ static void print_query(struct event *s_event){
printf("%s", s_event->qname); printf("%s", s_event->qname);
} }
/*
* This function save to log file the query section in rsylog format
* <time> <hostname> <procname>: <info> <data>
*/
static void query_to_log(struct event *s_event){
char t[32];
time_t ts = time(NULL);
char *req_type, *class, *type;
char tid[12];
char src[40];
char s_class[16], s_type[16];
if (syslog_time(ts, t, sizeof(t)) == 0)
fwrite(t, strlen(t), 1, f);
fwrite(" ", 1, 1, f);
fwrite(hostname, strlen(hostname), 1, f);
fwrite(" dns-trace: ", 12, 1, f);
fwrite("<info> ", 7, 1, f);
req_type = mapReqType(s_event->req_type);
fwrite(req_type, strlen(req_type), 1, f);
free(req_type);
fwrite(";", 1, 1, f);
snprintf(tid, 12, "tid=%x;", s_event->tid);
fwrite(tid, strlen(tid), 1, f);
snprintf(src, 40, "%s:%d;", inet_ntoa(*(struct in_addr*)&s_event->client), s_event->dport);
fwrite(src, strlen(src), 1, f);
class = mapClass(s_event->class);
snprintf(s_class, 16, "class=%s;", class);
fwrite(s_class, strlen(s_class), 1, f);
free(class);
type = mapType(s_event->type);
snprintf(s_type, 16, "type=%s;", type);
fwrite(s_type, strlen(s_type), 1, f);
free(type);
fwrite("\n", 1, 1, f);
}
/*
* This function get labels from DNS answer
*/
static void get_labels(unsigned char *buf, char *qname){ static void get_labels(unsigned char *buf, char *qname){
int pos = 0; int pos = 0;
while (*buf++ != '\0') { while (*buf++ != '\0') {
@@ -248,13 +325,32 @@ static void get_labels(unsigned char *buf, char *qname){
} }
qname[pos - 1] = '\0'; qname[pos - 1] = '\0';
} }
static void print_answer_hdr(struct event *s_event, int *pos, uint16_t *type, uint16_t *size, uint16_t *class, uint32_t *ttl){ /*
int p = *pos; * This function save to rsyslog format the answer section
uint16_t msg = s_event->buf[p++]; */
msg |= s_event->buf[p++] << 8; static void answer_to_log(struct event *s_event){
// printf("%x\n", ntohs(msg));
}
/*
* This function print to the stdout the answer section
*/
static void print_answer(struct event *s_event){
char *req_type; char *req_type;
int pos = 0;
char t[32];
time_t ts = time(NULL);
for (int i = 0; i < s_event->numAns; i++){
uint16_t type, class, size;
char *s_type, *s_class;
uint32_t ttl;
uint16_t msg = s_event->buf[pos++];
msg |= s_event->buf[pos++] << 8;
/* Print answer hdr */
syslog_time(ts, t, sizeof(t));
printf("%-20s", t);
req_type = mapReqType(s_event->req_type); req_type = mapReqType(s_event->req_type);
printf("%s ", req_type); printf("%s ", req_type);
free(req_type); free(req_type);
@@ -262,41 +358,26 @@ static void print_answer_hdr(struct event *s_event, int *pos, uint16_t *type, ui
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[p++]; type = s_event->buf[pos++];
*type |= s_event->buf[p++] << 8; type |= s_event->buf[pos++] << 8;
*class = s_event->buf[p++]; class = s_event->buf[pos++];
*class |= s_event->buf[p++] << 8; class |= s_event->buf[pos++] << 8;
*ttl = s_event->buf[p++]; ttl = s_event->buf[pos++];
*ttl |= s_event->buf[p++] << 8; ttl |= s_event->buf[pos++] << 8;
*ttl |= s_event->buf[p++] << 16; ttl |= s_event->buf[pos++] << 16;
*ttl |= s_event->buf[p++] << 24; ttl |= s_event->buf[pos++] << 24;
*size = s_event->buf[p++]; size = s_event->buf[pos++];
*size |= s_event->buf[p++] << 8; size |= s_event->buf[pos++] << 8;
*type = ntohs(*type); type = ntohs(type);
*class = ntohs(*class); class = ntohs(class);
*ttl = ntohl(*ttl); ttl = ntohl(ttl);
*size = ntohs(*size); size = ntohs(size);
*pos = p;
}
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){
int pos = 0;
for (int i = 0; i < s_event->numAns; i++){
// print_query(s_event);
uint16_t type, size, class;
uint32_t ttl;
char *s_type, *s_class;
print_answer_hdr(s_event, &pos, &type, &size, &class, &ttl);
/* Print answer data */
s_class = mapClass(class); s_class = mapClass(class);
printf("%-5s", s_class); printf("%-5s", s_class);
free(s_class); free(s_class);
@@ -315,16 +396,16 @@ int handle_event(void *ctx, void *data, size_t data_sz){
printf("%s %d ", cname, ttl); printf("%s %d ", cname, ttl);
} }
if (type == 28){ // -> AAAA if (type == 28){ // -> AAAA
int p = 0;
for (int i = 0; i < size; i++){ for (int i = 0; i < size; i++){
if (i % 2 == 0) if (i % 2 == 0)
printf("%x", s_event->buf[pos + p++]); printf("%x", s_event->buf[pos]);
else{ else{
if (i < (size - 1)) if (i < (size - 1))
printf("%x:", s_event->buf[pos + p++]); printf("%x:", s_event->buf[pos]);
else else
printf("%x", s_event->buf[pos + p++]); printf("%x", s_event->buf[pos]);
} }
pos++;
} }
printf(" %d ", ttl); printf(" %d ", ttl);
} }
@@ -332,6 +413,20 @@ int handle_event(void *ctx, void *data, size_t data_sz){
printf("\n"); printf("\n");
} }
} }
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){
if (arguments.to_output == 1)
print_query(s_event);
if (arguments.filename != NULL && f != NULL)
query_to_log(s_event);
}
if (s_event->req_type == REQ_ANSWER){
if (arguments.to_output == 1)
print_answer(s_event);
if (arguments.filename != NULL && f != NULL)
answer_to_log(s_event);
}
printf("\n"); printf("\n");
@@ -349,7 +444,7 @@ int main(int argc, char *argv[]){
arguments = parse_args(argc, argv); // Parsing arguments arguments = parse_args(argc, argv); // Parsing arguments
if (arguments.interface == NULL){ if (arguments.interface == NULL){
printf("You must specified the interface name"); printf("You must specified the interface name\n");
exit(-1); exit(-1);
} }
printf("Listen to %s\n", arguments.interface); printf("Listen to %s\n", arguments.interface);
@@ -360,6 +455,15 @@ int main(int argc, char *argv[]){
exit(-1); exit(-1);
} }
if (arguments.filename != NULL){
f = fopen(arguments.filename, "a");
if (f == NULL){
printf("Failed to create the file %s\n", arguments.filename);
return -1;
}
printf("Save to %s\n", arguments.filename);
}
signal(SIGINT, signalHandler); signal(SIGINT, signalHandler);
/* Open and load our eBPF object */ /* Open and load our eBPF object */
@@ -397,6 +501,9 @@ int main(int argc, char *argv[]){
setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd, sizeof(int)); setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd, sizeof(int));
/* Get the hostname of the system */
get_hostname();
/* Start the ringbuffer */ /* Start the ringbuffer */
rb = ring_buffer__new(fd_map_data, handle_event, NULL, NULL); rb = ring_buffer__new(fd_map_data, handle_event, NULL, NULL);
if (!rb){ if (!rb){
@@ -414,6 +521,9 @@ int main(int argc, char *argv[]){
} }
} }
if (f != NULL)
fclose(f);
ring_buffer__free(rb); ring_buffer__free(rb);
bpf_object__close(obj); bpf_object__close(obj);
+4 -5
View File
@@ -247,7 +247,7 @@ static void dnsanswer(struct __sk_buff *skb, struct iphdr ip, struct udphdr udp,
struct dnshdr dns; struct dnshdr dns;
uint32_t offset = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr); uint32_t offset = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr);
size_t tlen = ntohs(udp.len); size_t tlen = ntohs(udp.len);
int index = 0; unsigned int index = 0U;
if (tlen < 0 || tlen >= 256) if (tlen < 0 || tlen >= 256)
return; return;
@@ -297,13 +297,12 @@ 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){ //while (index < tlen){
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++; // index++;
} }
bpf_ringbuf_submit(s_event, 0); bpf_ringbuf_submit(s_event, 0);
//if(bpf_skb_load_bytes(skb, offset, &buf, tlen) < 0)
// bpf_printk("Failed");
} }
/* /*
Binary file not shown.
BIN
View File
Binary file not shown.
-14
View File
@@ -1,14 +0,0 @@
#include <stdio.h>
int main(void){
char buf[128] = "Hello world!";
char t = 'a';
//char *c = buf;
char *c = &t;
printf("%c\n", *c);
*c = buf[0];
printf("%c\n", *c);
return 0;
}