aboutsummaryrefslogtreecommitdiffstats
path: root/src/fnettrace-dns
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@protonmail.com>2022-04-08 08:49:51 -0400
committerLibravatar netblue30 <netblue30@protonmail.com>2022-04-08 08:49:51 -0400
commitf861764dfa4841a5743b49f33df923bfe75a7f84 (patch)
treef27e8b4a84479557ba0901985944c2ce4ce28b84 /src/fnettrace-dns
parentMerge branch 'master' of ssh://github.com/netblue30/firejail (diff)
downloadfirejail-f861764dfa4841a5743b49f33df923bfe75a7f84.tar.gz
firejail-f861764dfa4841a5743b49f33df923bfe75a7f84.tar.zst
firejail-f861764dfa4841a5743b49f33df923bfe75a7f84.zip
nettrace dns and sni
Diffstat (limited to 'src/fnettrace-dns')
-rw-r--r--src/fnettrace-dns/Makefile.in17
-rw-r--r--src/fnettrace-dns/fnettrace_dns.h34
-rw-r--r--src/fnettrace-dns/main.c162
3 files changed, 213 insertions, 0 deletions
diff --git a/src/fnettrace-dns/Makefile.in b/src/fnettrace-dns/Makefile.in
new file mode 100644
index 000000000..6c11e5bc8
--- /dev/null
+++ b/src/fnettrace-dns/Makefile.in
@@ -0,0 +1,17 @@
1.PHONY: all
2all: fnettrace-dns
3
4include ../common.mk
5
6%.o : %.c $(H_FILE_LIST)
7 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@
8
9fnettrace-dns: $(OBJS)
10 $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(EXTRA_LDFLAGS)
11
12.PHONY: clean
13clean:; rm -fr *.o fnettrace-dns *.gcov *.gcda *.gcno *.plist
14
15.PHONY: distclean
16distclean: clean
17 rm -fr Makefile
diff --git a/src/fnettrace-dns/fnettrace_dns.h b/src/fnettrace-dns/fnettrace_dns.h
new file mode 100644
index 000000000..db2e1a668
--- /dev/null
+++ b/src/fnettrace-dns/fnettrace_dns.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2014-2022 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#ifndef FNETTRACE_DNS_H
21#define FNETTRACE_DNS_H
22
23#include "../include/common.h"
24#include <unistd.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <netinet/in.h>
29#include <time.h>
30#include <stdarg.h>
31#include <fcntl.h>
32#include <sys/mman.h>
33
34#endif \ No newline at end of file
diff --git a/src/fnettrace-dns/main.c b/src/fnettrace-dns/main.c
new file mode 100644
index 000000000..0281b5157
--- /dev/null
+++ b/src/fnettrace-dns/main.c
@@ -0,0 +1,162 @@
1/*
2 * Copyright (C) 2014-2022 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "fnettrace_dns.h"
21#include <sys/ioctl.h>
22#include <time.h>
23#include <linux/filter.h>
24#include <linux/if_ether.h>
25#define MAX_BUF_SIZE (64 * 1024)
26
27// pkt - start of DNS layer
28void print_dns(uint32_t ip_src, unsigned char *pkt) {
29 assert(pkt);
30
31 char ip[30];
32 sprintf(ip, "%d.%d.%d.%d", PRINT_IP(ip_src));
33 time_t seconds = time(NULL);
34 struct tm *t = localtime(&seconds);
35
36 // expecting a single question count
37 if (pkt[4] != 0 || pkt[5] != 1)
38 goto errout;
39
40 // check cname
41 unsigned char *ptr = pkt + 12;
42 int len = 0;
43 while (*ptr != 0 && len < 255) { // 255 is the maximum length of a domain name including multiple '.'
44 if (*ptr > 63) // the name left of a '.' is 63 length maximum
45 goto errout;
46
47 int delta = *ptr + 1;
48 *ptr = '.';
49 len += delta;;
50 ptr += delta;
51 }
52
53 printf("%02d:%02d:%02d %15s %s\n", t->tm_hour, t->tm_min, t->tm_sec, ip, pkt + 12 + 1);
54 return;
55
56errout:
57 printf("%02d:%02d:%02d %15s Error: invalid DNS packet\n", t->tm_hour, t->tm_min, t->tm_sec, ip);
58}
59
60// https://www.kernel.org/doc/html/latest/networking/filter.html
61static void custom_bpf(int sock) {
62 struct sock_filter code[] = {
63 // sudo tcpdump ip and udp and src port 53 -dd
64 { 0x28, 0, 0, 0x0000000c },
65 { 0x15, 0, 8, 0x00000800 },
66 { 0x30, 0, 0, 0x00000017 },
67 { 0x15, 0, 6, 0x00000011 },
68 { 0x28, 0, 0, 0x00000014 },
69 { 0x45, 4, 0, 0x00001fff },
70 { 0xb1, 0, 0, 0x0000000e },
71 { 0x48, 0, 0, 0x0000000e },
72 { 0x15, 0, 1, 0x00000035 },
73 { 0x6, 0, 0, 0x00040000 },
74 { 0x6, 0, 0, 0x00000000 },
75 };
76
77 struct sock_fprog bpf = {
78 .len = (unsigned short) sizeof(code) / sizeof(code[0]),
79 .filter = code,
80 };
81
82 int rv = setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf));
83 if (rv < 0) {
84 fprintf(stderr, "Error: cannot attach BPF filter\n");
85 exit(1);
86 }
87}
88
89static void run_trace(void) {
90 // grab all Ethernet packets and use a custom BPF filter to get only UDP from source port 53
91 int s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
92 if (s < 0)
93 errExit("socket");
94 custom_bpf(s);
95
96 unsigned char buf[MAX_BUF_SIZE];
97 while (1) {
98 fd_set rfds;
99 FD_ZERO(&rfds);
100 FD_SET(s, &rfds);
101 struct timeval tv;
102 tv.tv_sec = 1;
103 tv.tv_usec = 0;
104 int rv = select(s + 1, &rfds, NULL, NULL, &tv);
105 if (rv < 0)
106 errExit("select");
107 else if (rv == 0)
108 continue;
109 unsigned bytes = recvfrom(s, buf, MAX_BUF_SIZE, 0, NULL, NULL);
110
111 if (bytes >= (14 + 20 + 8)) { // size of MAC + IP + UDP headers
112 uint8_t ip_hlen = (buf[14] & 0x0f) * 4;
113 uint16_t port_src;
114 memcpy(&port_src, buf + 14 + ip_hlen, 2);
115 port_src = ntohs(port_src);
116 uint8_t protocol = buf[14 + 9];
117 uint32_t ip_src;
118 memcpy(&ip_src, buf + 14 + 12, 4);
119 ip_src = ntohl(ip_src);
120
121 // if DNS packet, extract the query
122 if (port_src == 53 && protocol == 0x11) // UDP protocol
123 print_dns(ip_src, buf + 14 + ip_hlen + 8); // IP and UDP header len
124 }
125 }
126
127 close(s);
128}
129
130
131static void usage(void) {
132 printf("Usage: fnettrace-dns [OPTIONS]\n");
133 printf("Options:\n");
134 printf(" --help, -? - this help screen\n");
135 printf("\n");
136}
137
138int main(int argc, char **argv) {
139 int i;
140
141 for (i = 1; i < argc; i++) {
142 if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-?") == 0) {
143 usage();
144 return 0;
145 }
146 else {
147 fprintf(stderr, "Error: invalid argument\n");
148 return 1;
149 }
150 }
151
152 if (getuid() != 0) {
153 fprintf(stderr, "Error: you need to be root to run this program\n");
154 return 1;
155 }
156
157 time_t now = time(NULL);
158 printf("DNS trace for %s\n", ctime(&now));
159 run_trace();
160
161 return 0;
162}