Skip to content

Commit

Permalink
add supports statistics for DNSSEC validation resolver
Browse files Browse the repository at this point in the history
- SERVFAIL DNS message filter
- AD bit DNS message filter
- set custom mask for ClientSubnet
  • Loading branch information
mimuret committed Jun 19, 2017
1 parent 4db925c commit 1dcdbc1
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 6 deletions.
16 changes: 16 additions & 0 deletions src/client_ip_net_index.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "dns_message.h"
#include "md_array.h"
#include "hashtbl.h"
#include "syslog_debug.h"

static hashfunc ipnet_hashfunc;
static hashkeycmp ipnet_cmpfunc;
Expand Down Expand Up @@ -129,6 +130,21 @@ cip_net_indexer_init(void)
#endif
}

int
cip_net_v4_mask_set(const char *mask)
{
dsyslogf(LOG_INFO, "change v4 mask to %s", mask);
return inXaddr_pton(mask, &v4mask);
}
int
cip_net_v6_mask_set(const char *mask)
{
#if USE_IPV6
dsyslogf(LOG_INFO, "change v6 mask to %s", mask);
return inXaddr_pton(mask, &v6mask);
#endif
}

static unsigned int
ipnet_hashfunc(const void *key)
{
Expand Down
2 changes: 1 addition & 1 deletion src/daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ main(int argc, char *argv[])

pcap_thread_set_activate_mode(&pcap_thread, PCAP_THREAD_ACTIVATE_MODE_DELAYED);

cip_net_indexer_init();
dns_message_init();
if (parse_conf(argv[0])) {
return 1;
Expand All @@ -427,7 +428,6 @@ main(int argc, char *argv[])
country_indexer_init();
asn_indexer_init();
#endif
cip_net_indexer_init();
if ( !output_format_xml && !output_format_json ) {
output_format_xml = 1;
}
Expand Down
15 changes: 15 additions & 0 deletions src/dns_message.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ nxdomains_only_filter(const void *vp, const void *ctx)
return m->rcode == 3;
}

static int
ad_filter(const void *vp, const void *ctx)
{
const dns_message *m = vp;
return m->ad;
}

static int
popular_qtypes_filter(const void *vp, const void *ctx)
{
Expand Down Expand Up @@ -258,6 +265,12 @@ qname_filter(const void *vp, const void *ctx)
return (0 == regexec(r, m->qname, 0, NULL, 0));
}

static int
servfail_filter(const void *vp, const void *ctx)
{
const dns_message *m = vp;
return m->rcode == 2;
}
static indexer_t indexers[] = {
{"client", cip_indexer, cip_iterator, cip_reset},
{"server", sip_indexer, sip_iterator, sip_reset},
Expand Down Expand Up @@ -487,4 +500,6 @@ dns_message_init(void)
fl = md_array_filter_list_append(fl, md_array_create_filter("root-servers-net-only", root_servers_net_filter, 0));
fl = md_array_filter_list_append(fl, md_array_create_filter("chaos-class", chaos_class_filter, 0));
fl = md_array_filter_list_append(fl, md_array_create_filter("priming-query", priming_query_filter, 0));
fl = md_array_filter_list_append(fl, md_array_create_filter("servfail-only", servfail_filter, 0));
fl = md_array_filter_list_append(fl, md_array_create_filter("authentic-data-only", ad_filter, 0));
}
1 change: 1 addition & 0 deletions src/dns_message.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ struct _dns_message
unsigned int rd:1; /* set if RECUSION DESIRED bit is set */
unsigned int aa:1; /* set if AUTHORITATIVE ANSWER bit is set */
unsigned int tc:1; /* set if TRUNCATED RESPONSE bit is set */
unsigned int ad:1;
struct
{
unsigned int found:1; /* set if we found an OPT RR */
Expand Down
15 changes: 10 additions & 5 deletions src/dns_protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,14 +206,19 @@ dns_protocol_handler(const u_char * buf, uint16_t len, void *udata)
m.server_ip_addr = m.tm->src_ip_addr;
}

#if 0
tc = (us >> 9) & 0x01;
ra = (us >> 7) & 0x01;
#endif
m.opcode = (us >> 11) & 0x0F;
m.rd = (us >> 8) & 0x01;
m.aa = (us >> 10) & 0x01;
m.tc = (us >> 9) & 0x01;
m.rd = (us >> 8) & 0x01;
#if 0
ra = (us >> 7) & 0x01;
z = (us >> 6) & 0x01;
#endif
m.ad = (us >> 5) & 0x01;
#if 0
cd = (us >> 4) & 0x01;
#endif

m.rcode = us & 0x0F;

qdcount = nptohs(buf + 4);
Expand Down
14 changes: 14 additions & 0 deletions src/dsc.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ might have a dataset with \*(lqQuery Type\*(rq along one dimension and
\*(lqQuery Name Length\*(rq on the other. The result is a table that
shows the distribution of query name lengths for each query type.

\fBclient_v4_mask\fR " NETMASK " ;
Set the IPv4 MASK for client_subnet INDEXERS.

\fBclient_v6_mask\fR " NETMASK " ;
Set the IPv6 MASK for client_subnet INDEXERS.

A dataset has the following format:

\fBdatasets\fR NAME TYPE LABEL:FIRST LABEL:SECOND FILTERS [ PARAMETERS ] ;
Expand Down Expand Up @@ -496,6 +502,14 @@ and \fIversion.bind\fR queries.
.TP
\fBpriming-query\fR
Count only DNS messages where the query type is NS and QNAME is \*(lq.\*(rq.
.TP
\fBservfail-only\fR
Count only DNS response messages. A query is a DNS message
where the RCODE is set to 2.
\fBauthentic-data-only\fR
Count only DNS response messages. A query is a DNS message
where the AD bit is set to 1.

.SH "QNAME FILTERS"
Defines a custom QNAME-based filter for DNS messages. If you
refer to this named filter on a dataset line, then only queries
Expand Down
12 changes: 12 additions & 0 deletions src/dsc.conf.sample.in
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ dataset direction_vs_ipproto ip Direction:ip_direction IPProto:ip_proto any;
# dataset for monitoring an authoritative nameserver for DNS reflection attack
#dataset qr_aa_bits dns Direction:ip_direction QRAABits:qr_aa_bits any;

# dataset for servfail response for dnssec validation fail.
#dataset servfail_qname dns ALL:null Qname:qname servfail-only,replies-only;

# dataset for successful validation.
#dataset ad_qname dns ALL:null Qname:qname authentic-data-only,replies-only;
# bpf_vlan_tag_byte_order
#
# Set this to 'host' on FreeBSD-4 where the VLAN id that we
Expand Down Expand Up @@ -184,3 +189,10 @@ dataset direction_vs_ipproto ip Direction:ip_direction IPProto:ip_proto any;
#geoip_v6_dat "/usr/share/GeoIP/GeoIPv6.dat";
#geoip_asn_v4_dat "/usr/share/GeoIP/GeoIPASNum.dat" MEMORY_CACHE;
#geoip_asn_v6_dat "/usr/share/GeoIP/GeoIPASNumv6.dat" MEMORY_CACHE;

# client_subnet mask
#
# Set clientSubnet netmask
#
# client_v4_mask "255.255.255.0"
# client_v6_mask "ffff:ffff:ffff:ffff:ffff:ffff:0000:0000"
36 changes: 36 additions & 0 deletions src/parse_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,32 @@ int parse_conf_drop_ip_fragments(const conf_token_t* tokens) {
return 0;
}

int parse_conf_client_v4_mask(const conf_token_t* tokens) {
char* mask = strndup(tokens[1].token, tokens[1].length);
int ret;
if (!mask) {
errno = ENOMEM;
return -1;
}

ret = cip_net_v4_mask_set(mask);
free(mask);
return ret == 1 ? 0 : 1;
}
int parse_conf_client_v6_mask(const conf_token_t* tokens) {
char* mask = strndup(tokens[1].token, tokens[1].length);
int ret;

if (!mask) {
errno = ENOMEM;
return -1;
}

ret = cip_net_v6_mask_set(mask);
free(mask);
return ret == 1 ? 0 : 1;
}

static conf_token_syntax_t _syntax[] = {
{
"interface",
Expand Down Expand Up @@ -660,6 +686,16 @@ static conf_token_syntax_t _syntax[] = {
parse_conf_drop_ip_fragments,
{ TOKEN_END }
},
{
"client_v4_mask",
parse_conf_client_v4_mask,
{ TOKEN_STRING, TOKEN_END }
},
{
"client_v6_mask",
parse_conf_client_v6_mask,
{ TOKEN_STRING, TOKEN_END }
},

{ 0, 0, { TOKEN_END } }
};
Expand Down

0 comments on commit 1dcdbc1

Please sign in to comment.