Update project
This commit is contained in:
parent
2cb21c1f55
commit
65258eb429
BIN
dns-trace
BIN
dns-trace
Binary file not shown.
BIN
dns4.pcap
Normal file
BIN
dns4.pcap
Normal file
Binary file not shown.
@ -28,6 +28,12 @@ struct event {
|
|||||||
char ans[32];
|
char ans[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct query_section{
|
||||||
|
char qname[QNAME_SIZE];
|
||||||
|
int class;
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
|
||||||
struct dns_answer {
|
struct dns_answer {
|
||||||
uint16_t tid;
|
uint16_t tid;
|
||||||
char qname[QNAME_SIZE];
|
char qname[QNAME_SIZE];
|
||||||
|
@ -35,22 +35,59 @@ struct {
|
|||||||
__type(value, struct dns_answer);
|
__type(value, struct dns_answer);
|
||||||
} m_tid SEC(".maps");
|
} m_tid SEC(".maps");
|
||||||
|
|
||||||
|
static size_t get_labels(struct __sk_buff *skb, size_t offset, size_t end, struct event *s_event, struct query_section *s_query){
|
||||||
|
size_t len;
|
||||||
|
unsigned char buf[256];
|
||||||
|
unsigned char *c;
|
||||||
|
int index = 0;
|
||||||
|
int qname_len = 0; // Full length of the qname field
|
||||||
|
|
||||||
|
bpf_skb_load_bytes(skb, offset, &buf, 41);
|
||||||
|
c = buf;
|
||||||
|
|
||||||
|
while (*(c++) != '\0') {
|
||||||
|
if(*c >= 'a' && *c <= 'z')
|
||||||
|
s_event->qname[index] = *c;
|
||||||
|
else if(*c >= 'A' && *c <= 'Z')
|
||||||
|
s_event->qname[index] = *c;
|
||||||
|
else
|
||||||
|
s_event->qname[index] = '.';
|
||||||
|
index++;
|
||||||
|
qname_len++;
|
||||||
|
}
|
||||||
|
s_event->qname[--index] = '\0';
|
||||||
|
qname_len++; // For the null character
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function get the query field and the return the length of it
|
* This function get the query field and the return the length of it
|
||||||
*/
|
*/
|
||||||
static size_t get_query(struct __sk_buff *skb, struct event *s_event, uint16_t *class, uint16_t *type, size_t tlen){
|
//static size_t get_query_section(struct __sk_buff *skb, struct event *s_event, uint16_t *class, uint16_t *type, uint8_t tlen){
|
||||||
|
static size_t get_query_section(struct __sk_buff *skb, struct event *s_event, struct query_section *s_query, uint8_t offset){
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[QNAME_SIZE] = {0};
|
char buf[256] = {0};
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int qname_len = 0; // Full length of the qname field
|
int qname_len = 0; // Full length of the qname field
|
||||||
char qname[QNAME_SIZE] = {0};
|
char qname[QNAME_SIZE] = {0};
|
||||||
char *c;
|
char *c;
|
||||||
|
uint8_t flen = skb->len;
|
||||||
|
/*
|
||||||
|
We get the size for the buffer
|
||||||
|
We substract the full size of the buffer (skb->len) with the sizes of each headers (eth + ip + udp + dns header)
|
||||||
|
*/
|
||||||
|
uint8_t l = flen - offset;
|
||||||
|
|
||||||
|
if (l < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
//bpf_skb_load_bytes(skb, tlen, &buf, l);
|
||||||
bpf_skb_load_bytes(skb, tlen, &buf, 41);
|
bpf_skb_load_bytes(skb, offset, &buf, 41);
|
||||||
c = buf;
|
c = buf;
|
||||||
|
|
||||||
|
// get_labels(struct __sk_buff *skb, size_t offset, size_t end, struct event *s_event, struct query_section *s_query)
|
||||||
|
// get_labels(skb, offset, 41, s_event, s_query);
|
||||||
/*
|
/*
|
||||||
* The qname is composed by a the number of bytes then follow by the label
|
* The qname is composed by a the number of bytes then follow by the label
|
||||||
* For instance, for the qname www.bucchino.org,
|
* For instance, for the qname www.bucchino.org,
|
||||||
@ -72,18 +109,35 @@ static size_t get_query(struct __sk_buff *skb, struct event *s_event, uint16_t *
|
|||||||
}
|
}
|
||||||
s_event->qname[--index] = '\0';
|
s_event->qname[--index] = '\0';
|
||||||
qname_len++; // For the null character
|
qname_len++; // For the null character
|
||||||
bpf_printk("%s (%d) %d", s_event->qname, index, qname_len);
|
// bpf_printk("l: %d", l);
|
||||||
|
|
||||||
// Get class and type
|
// Get class and type
|
||||||
len = qname_len;
|
len = qname_len;
|
||||||
bpf_skb_load_bytes(skb, tlen + qname_len, type, sizeof(uint16_t));
|
bpf_skb_load_bytes(skb, offset + qname_len, &s_query->type, sizeof(uint16_t));
|
||||||
len += 2;
|
len += 2;
|
||||||
bpf_skb_load_bytes(skb, tlen + qname_len + 2, class, sizeof(uint16_t));
|
bpf_skb_load_bytes(skb, offset + qname_len + 2, &s_query->class, sizeof(uint16_t));
|
||||||
len += 2;
|
len += 2;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
static size_t get_answer(struct __sk_buff *skb, struct event *s_event, size_t tlen){
|
||||||
|
size_t len = 0;
|
||||||
|
unsigned char buf[256] = {0}; // Need to be unsigned, otherwise, the result is fffff
|
||||||
|
|
||||||
|
if(bpf_skb_load_bytes(skb, tlen, &buf, 2) < 0)
|
||||||
|
return 0;
|
||||||
|
/*
|
||||||
|
* 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 it's the pointer and 0x00c is the position in the DNS header
|
||||||
|
*/
|
||||||
|
if (buf[0] == 0xc0){
|
||||||
|
bpf_printk("Pointer to %x", buf[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* https://datatracker.ietf.org/doc/html/rfc1035
|
* https://datatracker.ietf.org/doc/html/rfc1035
|
||||||
*/
|
*/
|
||||||
@ -91,8 +145,7 @@ static int dnsquery(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip, s
|
|||||||
struct event *s_event;
|
struct event *s_event;
|
||||||
struct dnshdr dns = {0};
|
struct dnshdr dns = {0};
|
||||||
char saddr[32];
|
char saddr[32];
|
||||||
uint16_t class, type;
|
struct query_section s_query = {0};
|
||||||
//struct dns_answer s_dnsanswer;
|
|
||||||
// bpf_printk("udp len: %d", ntohs(udp.len));
|
// bpf_printk("udp len: %d", ntohs(udp.len));
|
||||||
|
|
||||||
s_event = bpf_ringbuf_reserve(&m_data, sizeof(*s_event), 0);
|
s_event = bpf_ringbuf_reserve(&m_data, sizeof(*s_event), 0);
|
||||||
@ -105,6 +158,15 @@ static int dnsquery(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip, s
|
|||||||
/* Get DNS header */
|
/* Get DNS header */
|
||||||
bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr), &dns, sizeof(struct dnshdr));
|
bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr), &dns, sizeof(struct dnshdr));
|
||||||
|
|
||||||
|
// Check OpCode
|
||||||
|
uint16_t flags = ntohs(dns.flags);
|
||||||
|
uint16_t qr = flags & 0xF000; // Get the QR code: 0 -> query, 1 -> response
|
||||||
|
if (qr == 0x0)
|
||||||
|
bpf_printk("Query");
|
||||||
|
else if(qr == 0x8000)
|
||||||
|
bpf_printk("Response");
|
||||||
|
bpf_printk("Flags: %x %x", flags, qr);
|
||||||
|
|
||||||
if (ntohs(dns.nbQuestions) == 0){
|
if (ntohs(dns.nbQuestions) == 0){
|
||||||
bpf_ringbuf_discard(s_event, 0);
|
bpf_ringbuf_discard(s_event, 0);
|
||||||
return 0;
|
return 0;
|
||||||
@ -123,14 +185,15 @@ static int dnsquery(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip, s
|
|||||||
|
|
||||||
|
|
||||||
/* Get the query structure */
|
/* Get the query structure */
|
||||||
size_t tlen = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr);
|
uint8_t tlen = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr);
|
||||||
size_t query_len = get_query(skb, s_event, &class, &type, tlen);
|
// size_t query_len = get_query_section(skb, s_event, &class, &type, tlen);
|
||||||
|
size_t query_len = get_query_section(skb, s_event, &s_query, tlen);
|
||||||
|
|
||||||
// https://docs.cilium.io/en/stable/reference-guides/bpf/progtypes/
|
// https://docs.cilium.io/en/stable/reference-guides/bpf/progtypes/
|
||||||
s_event->dport = dport;
|
s_event->dport = dport;
|
||||||
s_event->sport = sport;
|
s_event->sport = sport;
|
||||||
s_event->class = ntohs(class);
|
s_event->class = ntohs(s_query.class);
|
||||||
s_event->type = ntohs(type);
|
s_event->type = ntohs(s_query.type);
|
||||||
//if(bpf_probe_read_user_str(&s_event->qname, sizeof(s_event->qname), qname) < 0)
|
//if(bpf_probe_read_user_str(&s_event->qname, sizeof(s_event->qname), qname) < 0)
|
||||||
// bpf_printk("Failed to copy qname");
|
// bpf_printk("Failed to copy qname");
|
||||||
|
|
||||||
@ -146,14 +209,26 @@ static int dnsanswer(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip,
|
|||||||
struct dnshdr dns = {0};
|
struct dnshdr dns = {0};
|
||||||
uint16_t tid = 0;
|
uint16_t tid = 0;
|
||||||
struct dns_answer s_dnsanswer;
|
struct dns_answer s_dnsanswer;
|
||||||
|
struct query_section s_query = {0};
|
||||||
/* Get DNS header */
|
|
||||||
bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr), &dns, sizeof(struct dnshdr));
|
|
||||||
|
|
||||||
s_event = bpf_ringbuf_reserve(&m_data, sizeof(*s_event), 0);
|
s_event = bpf_ringbuf_reserve(&m_data, sizeof(*s_event), 0);
|
||||||
if (!s_event)
|
if (!s_event)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* Get DNS header */
|
||||||
|
bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr), &dns, sizeof(struct dnshdr));
|
||||||
|
|
||||||
|
// Check OpCode
|
||||||
|
uint16_t flags = ntohs(dns.flags);
|
||||||
|
uint16_t qr = flags & 0xF000; // Get the QR code: 0 -> query, 1 -> response
|
||||||
|
if (qr == 0x0){} // Query
|
||||||
|
else if(qr == 0x8000){} // Response
|
||||||
|
|
||||||
|
if (ntohs(dns.nbQuestions) == 0 && ntohs(dns.nbAnswerRRs)){
|
||||||
|
bpf_ringbuf_discard(s_event, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the Transaction ID */
|
/* Get the Transaction ID */
|
||||||
tid = ntohs(dns.transactionID);
|
tid = ntohs(dns.transactionID);
|
||||||
bpf_printk("tid: %x", tid);
|
bpf_printk("tid: %x", tid);
|
||||||
@ -176,13 +251,19 @@ static int dnsanswer(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Get the query response */
|
/* Get the query response */
|
||||||
size_t tlen = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr);
|
uint8_t tlen = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr);
|
||||||
uint16_t class, type;
|
uint16_t class, type;
|
||||||
size_t query_len = get_query(skb, s_event, &class, &type, tlen);
|
// size_t query_len = get_query_section(skb, s_event, &class, &type, tlen);
|
||||||
|
size_t query_len = get_query_section(skb, s_event, &s_query, tlen);
|
||||||
bpf_printk("answer qname: %s", s_event->qname);
|
bpf_printk("answer qname: %s", s_event->qname);
|
||||||
|
s_event->dport = dport;
|
||||||
|
s_event->sport = sport;
|
||||||
|
s_event->class = ntohs(class);
|
||||||
|
s_event->type = ntohs(type);
|
||||||
|
|
||||||
/* Get the answer */
|
/* Get the answer */
|
||||||
|
tlen += query_len;
|
||||||
|
size_t answer_len = get_answer(skb, s_event, tlen);
|
||||||
bpf_ringbuf_submit(s_event, 0);
|
bpf_ringbuf_submit(s_event, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user