Update
This commit is contained in:
parent
1449cc961d
commit
be9022d0a6
2
Makefile
2
Makefile
@ -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
cname.pcap
BIN
cname.pcap
Binary file not shown.
BIN
dns-trace
BIN
dns-trace
Binary file not shown.
18
dns-trace_2025-02-08.log
Normal file
18
dns-trace_2025-02-08.log
Normal 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
dns.pcap
BIN
dns.pcap
Binary file not shown.
BIN
dns10.pcap
BIN
dns10.pcap
Binary file not shown.
BIN
dns2.pcap
BIN
dns2.pcap
Binary file not shown.
BIN
dns3.pcap
BIN
dns3.pcap
Binary file not shown.
BIN
dns4.pcap
BIN
dns4.pcap
Binary file not shown.
2
exec.sh
2
exec.sh
@ -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
jvetter.pcap
BIN
jvetter.pcap
Binary file not shown.
BIN
src/.dns-trace.c.swp
Normal file
BIN
src/.dns-trace.c.swp
Normal file
Binary file not shown.
192
src/dns-trace.c
192
src/dns-trace.c
@ -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,22 +396,36 @@ 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);
|
||||||
}
|
}
|
||||||
pos += size;
|
pos += size;
|
||||||
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);
|
||||||
|
|
||||||
|
@ -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
test
BIN
test
Binary file not shown.
14
test.c
14
test.c
@ -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;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user