Skip to content

Commit

Permalink
Initial NXDOMAIN implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
gamelinux committed Mar 17, 2012
1 parent 94fb37d commit 67b5094
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 26 deletions.
163 changes: 137 additions & 26 deletions src/dns.c
Expand Up @@ -12,10 +12,11 @@


static int archive(packetinfo *pi, ldns_pkt *decoded_dns); static int archive(packetinfo *pi, ldns_pkt *decoded_dns);
static int archive_query(packetinfo *pi, ldns_pkt *decoded_dns); static int archive_query(packetinfo *pi, ldns_pkt *decoded_dns);
static int archive_lname_list(packetinfo *pi, ldns_rdf *lname,ldns_rr_list *list, ldns_buffer *buf, uint8_t rcode); static int archive_lname_list(packetinfo *pi, ldns_rdf *lname,ldns_rr_list *list, ldns_buffer *buf, ldns_pkt *decoded_dns);
void associated_lookup_or_make_insert(pdns_record *lname_node, packetinfo *pi, unsigned char *rname_str, ldns_rr *rr); void associated_lookup_or_make_insert(pdns_record *lname_node, packetinfo *pi, unsigned char *rname_str, ldns_rr *rr);
pdns_record *pdnsr_lookup_or_make_new(uint64_t dnshash, packetinfo *pi, unsigned char *lname_str); pdns_record *pdnsr_lookup_or_make_new(uint64_t dnshash, packetinfo *pi, unsigned char *lname_str);
void print_passet(pdns_asset *p, pdns_record *l); void print_passet(pdns_asset *p, pdns_record *l);
void print_passet_nxd(pdns_record *l, ldns_rdf *lname, ldns_rr *rr);
const char *u_ntop(const struct in6_addr ip_addr, int af, char *dest); const char *u_ntop(const struct in6_addr ip_addr, int af, char *dest);
void expire_dns_assets(pdns_record *pdnsr, time_t expire_t); void expire_dns_assets(pdns_record *pdnsr, time_t expire_t);
void delete_dns_record (pdns_record * pdnsr, pdns_record ** bucket_ptr); void delete_dns_record (pdns_record * pdnsr, pdns_record ** bucket_ptr);
Expand Down Expand Up @@ -213,7 +214,7 @@ archive_query(packetinfo *pi, ldns_pkt *decoded_dns)
rdf_data = ldns_rr_owner(question_rr); rdf_data = ldns_rr_owner(question_rr);


dlog("[D] rdf_data = %p\n", rdf_data); dlog("[D] rdf_data = %p\n", rdf_data);
ret = archive_lname_list(pi, rdf_data, questions, dns_buffer, rcode); ret = archive_lname_list(pi, rdf_data, questions, dns_buffer, decoded_dns);


if (ret < 0) { if (ret < 0) {
dlog("[D] archive_lname_list() returned error\n"); dlog("[D] archive_lname_list() returned error\n");
Expand All @@ -228,28 +229,21 @@ archive(packetinfo *pi, ldns_pkt *decoded_dns)
{ {
ldns_buffer *dns_buffer; ldns_buffer *dns_buffer;
int qa_rrcount; int qa_rrcount;
int an_rrcount;
int au_rrcount;
int i; int i;
uint8_t rcode;
ldns_rr_list *questions; ldns_rr_list *questions;
ldns_rr_list *answers; ldns_rr_list *answers;
ldns_rr_list *authorities;


questions = ldns_pkt_question(decoded_dns); questions = ldns_pkt_question(decoded_dns);
answers = ldns_pkt_answer(decoded_dns); answers = ldns_pkt_answer(decoded_dns); // Move -> archive_lname_list
authorities = ldns_pkt_authority(decoded_dns);


qa_rrcount = ldns_rr_list_rr_count(questions); qa_rrcount = ldns_rr_list_rr_count(questions);
an_rrcount = ldns_rr_list_rr_count(answers);
au_rrcount = ldns_rr_list_rr_count(authorities);


dns_buffer = ldns_buffer_new(LDNS_MIN_BUFLEN); dns_buffer = ldns_buffer_new(LDNS_MIN_BUFLEN);
rcode = ldns_pkt_get_rcode(decoded_dns);


dlog("[*] %d qa_rrcount\n", qa_rrcount); dlog("[*] %d qa_rrcount\n", qa_rrcount);



// Do we ever have more than one Question?
// If we do - are we handling it correct ?
for (i = 0; i < qa_rrcount; i++) { for (i = 0; i < qa_rrcount; i++) {
ldns_rr *question_rr; ldns_rr *question_rr;
ldns_rdf *rdf_data; ldns_rdf *rdf_data;
Expand All @@ -262,7 +256,7 @@ archive(packetinfo *pi, ldns_pkt *decoded_dns)


/* plop all the answers into the correct archive_node_t's /* plop all the answers into the correct archive_node_t's
* associated_nodes hash. */ * associated_nodes hash. */
ret = archive_lname_list(pi, rdf_data, answers, dns_buffer, rcode); ret = archive_lname_list(pi, rdf_data, answers, dns_buffer, decoded_dns);


if (ret < 0) { if (ret < 0) {
dlog("[D] archive_lname_list() returned error\n"); dlog("[D] archive_lname_list() returned error\n");
Expand All @@ -278,14 +272,15 @@ archive_lname_list(packetinfo *pi,
ldns_rdf *lname, ldns_rdf *lname,
ldns_rr_list *list, ldns_rr_list *list,
ldns_buffer *buf, ldns_buffer *buf,
uint8_t rcode) ldns_pkt *decoded_dns)
{ {
int list_count; int list_count;
unsigned char *lname_str = 0; unsigned char *lname_str = 0;
ldns_status status; ldns_status status;
int i; int i;
pdns_record *lname_node = NULL; pdns_record *lname_node = NULL;
uint64_t dnshash; uint64_t dnshash;
uint8_t rcode;


ldns_buffer_clear(buf); ldns_buffer_clear(buf);
status = ldns_rdf2buffer_str(buf, lname); status = ldns_rdf2buffer_str(buf, lname);
Expand All @@ -306,8 +301,10 @@ archive_lname_list(packetinfo *pi,
dlog("[D] lname_str:%s\n", lname_str); dlog("[D] lname_str:%s\n", lname_str);
dlog("[D] list_count:%d\n",list_count); dlog("[D] list_count:%d\n",list_count);


rcode = ldns_pkt_get_rcode(decoded_dns);

if (list_count == 0 && rcode == 3) { if (list_count == 0 && rcode == 3) {
dlog("[D] NXDOMAIN\n"); dlog("[D] NXDOMAIN: %s\n", lname_str);
/* PROBLEM: /* PROBLEM:
* As there is no valid ldns_rr here and we cant fake one that will * As there is no valid ldns_rr here and we cant fake one that will
* be very unique, we cant push this to the normal * be very unique, we cant push this to the normal
Expand All @@ -318,25 +315,32 @@ archive_lname_list(packetinfo *pi,
* if the bucket is to big or non efficient. We would still store data * if the bucket is to big or non efficient. We would still store data
* such as: fistseen,lastseen,client_ip,server_ip,class,query,NXDOMAIN * such as: fistseen,lastseen,client_ip,server_ip,class,query,NXDOMAIN
*/ */

/*
if (config.dnsf & DNS_CHK_NXDOMAIN) { if (config.dnsf & DNS_CHK_NXDOMAIN) {
ldns_rr_list *questions;
ldns_rr_class class;
ldns_rr_type type;
ldns_rr *rr;

// CHECK IF THE NODE EXISTS, IF NOT MAKE IT - RETURN POINTER TO NODE // CHECK IF THE NODE EXISTS, IF NOT MAKE IT - RETURN POINTER TO NODE
if (lname_node == NULL) { if (lname_node == NULL) {
dnshash = hash(lname_str); dnshash = hash(lname_str);
dlog("[D] Hash: %lu\n", dnshash); dlog("[D] Hash: %lu\n", dnshash);
lname_node = pdnsr_lookup_or_make_new(dnshash, pi, lname_str); lname_node = pdnsr_lookup_or_make_new(dnshash, pi, lname_str);
} }
unsigned char *rname_str = 0; /* Set the NXDOMAIN flag: */
dlog("[D] rname_str:%s\n", rname_str); //lname_node->nxflag |= DNS_NXDOMAIN;
questions = ldns_pkt_question(decoded_dns);
// CHECK IF THE NODE HAS THE ASSOCIATED ENTRY, IF NOT ADD IT. rr = ldns_rr_list_rr(questions, 0);
associated_lookup_or_make_insert(lname_node, pi, rname_str, rr); class = ldns_rr_get_class(rr);
free(rname_str); type = ldns_rr_get_type(rr);
/* Print the NXDOMAIN */
if ((lname_node->last_seen - lname_node->last_print) >= config.dnsprinttime) {
print_passet_nxd(lname_node, lname, rr);
lname_node->seen = 0;
}
} }
free(lname_str); free(lname_str);
return(0); return(0);
*/
} }


for (i = 0; i < list_count; i++) { for (i = 0; i < list_count; i++) {
Expand Down Expand Up @@ -565,6 +569,107 @@ const char *u_ntop(const struct in6_addr ip_addr, int af, char *dest)
return dest; return dest;
} }


void print_passet_nxd(pdns_record *l, ldns_rdf *lname, ldns_rr *rr){
FILE *fd;
uint8_t screen;
static char ip_addr_s[INET6_ADDRSTRLEN];
static char ip_addr_c[INET6_ADDRSTRLEN];

if (config.logfile[0] == '-' && config.logfile[1] == '\0' ) {
if (config.handle == NULL) return;
screen = 1;
fd = stdout;
} else {
screen = 0;
fd = fopen(config.logfile, "a");
if (fd == NULL) {
plog("[E] ERROR: Cant open file %s\n",config.logfile);
l->last_print = l->last_seen;
return;
}
}

u_ntop(l->sip, l->af, ip_addr_s);
u_ntop(l->cip, l->af, ip_addr_c);

/* example output:
* 1329575805||100.240.60.160||80.160.30.30||IN||sadf.googles.com.||A||NXDOMAIN||0
*/
fprintf(fd,"%lu||%s||%s||",l->last_seen, ip_addr_c, ip_addr_s);

switch (ldns_rr_get_class(rr)) {
case LDNS_RR_CLASS_IN:
fprintf(fd,"IN");
break;
case LDNS_RR_CLASS_CH:
fprintf(fd,"CH");
break;
case LDNS_RR_CLASS_HS:
fprintf(fd,"HS");
break;
case LDNS_RR_CLASS_NONE:
fprintf(fd,"NONE");
break;
case LDNS_RR_CLASS_ANY:
fprintf(fd,"ANY");
break;
default:
fprintf(fd,"%d",ldns_rr_get_class(rr));
break;
}

fprintf(fd,"||%s||",l->qname);

switch (ldns_rr_get_type(rr)) {
case LDNS_RR_TYPE_PTR:
fprintf(fd,"PTR");
break;
case LDNS_RR_TYPE_A:
fprintf(fd,"A");
break;
case LDNS_RR_TYPE_AAAA:
fprintf(fd,"AAAA");
break;
case LDNS_RR_TYPE_CNAME:
fprintf(fd,"CNAME");
break;
case LDNS_RR_TYPE_DNAME:
fprintf(fd,"DNAME");
break;
case LDNS_RR_TYPE_NAPTR:
fprintf(fd,"NAPTR");
break;
case LDNS_RR_TYPE_RP:
fprintf(fd,"RP");
break;
case LDNS_RR_TYPE_SRV:
fprintf(fd,"SRV");
break;
case LDNS_RR_TYPE_TXT:
fprintf(fd,"TXT");
break;
case LDNS_RR_TYPE_SOA:
fprintf(fd,"SOA");
break;
case LDNS_RR_TYPE_NS:
fprintf(fd,"NS");
break;
case LDNS_RR_TYPE_MX:
fprintf(fd,"MX");
break;
default:
fprintf(fd,"%d",ldns_rdf_get_type(lname));
break;
}

fprintf(fd,"||NXDOMAIN||0\n");

if (screen == 0)
fclose(fd);

l->last_print = l->last_seen;
}

void print_passet(pdns_asset *p, pdns_record *l) { void print_passet(pdns_asset *p, pdns_record *l) {


FILE *fd; FILE *fd;
Expand Down Expand Up @@ -675,8 +780,8 @@ pdns_record *pdnsr_lookup_or_make_new(uint64_t dnshash, packetinfo *pi, unsigned
// if found, update & return dnsr // if found, update & return dnsr
if (strcmp((const char *)lname_str,(const char *)pdnsr->qname) == 0) { // match :) if (strcmp((const char *)lname_str,(const char *)pdnsr->qname) == 0) { // match :)
pdnsr->last_seen = pi->pheader->ts.tv_sec; pdnsr->last_seen = pi->pheader->ts.tv_sec;
pdnsr->sip = pi->cxt->s_ip; pdnsr->cip = pi->cxt->s_ip; // This should always be the client IP
pdnsr->cip = pi->cxt->d_ip; pdnsr->sip = pi->cxt->d_ip; // This should always be the server IP
return pdnsr; return pdnsr;
} }
pdnsr = pdnsr->next; pdnsr = pdnsr->next;
Expand All @@ -696,6 +801,7 @@ pdns_record *pdnsr_lookup_or_make_new(uint64_t dnshash, packetinfo *pi, unsigned
pdnsr->first_seen = pi->pheader->ts.tv_sec; pdnsr->first_seen = pi->pheader->ts.tv_sec;
pdnsr->last_seen = pi->pheader->ts.tv_sec; pdnsr->last_seen = pi->pheader->ts.tv_sec;
pdnsr->af = pi->cxt->af; pdnsr->af = pi->cxt->af;
pdnsr->nxflag = 0;
pdnsr->sip = pi->cxt->s_ip; pdnsr->sip = pi->cxt->s_ip;
pdnsr->cip = pi->cxt->d_ip; pdnsr->cip = pi->cxt->d_ip;
pdnsr->next = head; pdnsr->next = head;
Expand Down Expand Up @@ -1006,6 +1112,11 @@ void parse_dns_flags (char *args)
dlog("[D] Enabling flag: DNS_CHK_NS\n"); dlog("[D] Enabling flag: DNS_CHK_NS\n");
ok++; ok++;
break; break;
case 'x': // NXDOMAIN
config.dnsf |= DNS_CHK_NXDOMAIN;
dlog("[D] Enabling flag: DNS_CHK_NXDOMAIN\n");
ok++;
break;
case '\0': case '\0':
dlog("[W] Bad DNS flag - ending flag checks!\n"); dlog("[W] Bad DNS flag - ending flag checks!\n");
ok = 0; ok = 0;
Expand Down
8 changes: 8 additions & 0 deletions src/dns.h
Expand Up @@ -17,6 +17,11 @@ void parse_dns_flags (char *args);
#define DNS_CHK_SOA 0x0200 #define DNS_CHK_SOA 0x0200
#define DNS_CHK_MX 0x0400 #define DNS_CHK_MX 0x0400
#define DNS_CHK_NS 0x0800 #define DNS_CHK_NS 0x0800
// Last one is nxdomain
#define DNS_CHK_NXDOMAIN 0x8000

// Flag for indicating an NXDOMAIN
#define DNS_NXDOMAIN 0x01


/* To avoid spaming the logfile with duplicate dns info /* To avoid spaming the logfile with duplicate dns info
* we only print a dns record one time each 24H. This way * we only print a dns record one time each 24H. This way
Expand Down Expand Up @@ -73,7 +78,10 @@ typedef struct _pdns_asset {
typedef struct _pdns_record { typedef struct _pdns_record {
time_t first_seen; /* First seen (unix timestamp) */ time_t first_seen; /* First seen (unix timestamp) */
time_t last_seen; /* Last seen (unix timestamp) */ time_t last_seen; /* Last seen (unix timestamp) */
time_t last_print; /* Last time record(NXD) was printet */
uint64_t seen; /* Number of times seen */
unsigned char *qname; /* Query name (gamelinux.org) */ unsigned char *qname; /* Query name (gamelinux.org) */
uint8_t nxflag; /* Flag to indicate if this is a NXDOMAIN */
uint32_t af; /* IP version (4/6) AF_INET */ uint32_t af; /* IP version (4/6) AF_INET */
struct in6_addr sip; /* DNS Server IP (v4/6) */ struct in6_addr sip; /* DNS Server IP (v4/6) */
struct in6_addr cip; /* DNS Client IP (v4/6) */ struct in6_addr cip; /* DNS Client IP (v4/6) */
Expand Down
1 change: 1 addition & 0 deletions src/passivedns.c
Expand Up @@ -1023,6 +1023,7 @@ int main(int argc, char *argv[])
// config.dnsf |= DNS_CHK_SOA; // config.dnsf |= DNS_CHK_SOA;
// config.dnsf |= DNS_CHK_NS; // config.dnsf |= DNS_CHK_NS;
// config.dnsf |= DNS_CHK_MX; // config.dnsf |= DNS_CHK_MX;
config.dnsf |= DNS_CHK_NXDOMAIN;


signal(SIGTERM, game_over); signal(SIGTERM, game_over);
signal(SIGINT, game_over); signal(SIGINT, game_over);
Expand Down

0 comments on commit 67b5094

Please sign in to comment.