-
-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added sampling to dnscap #15
base: develop
Are you sure you want to change the base?
Changes from 7 commits
add5fb8
0fbc9c2
2a5449e
949db6e
7705450
db0467b
a527e69
12d1fd3
5ece843
53bb6b9
423990b
31a4215
9581375
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -128,6 +128,7 @@ static const char version_fmt[] = "V1.0-OARC-r%d (%s)"; | |
#include <time.h> | ||
#include <unistd.h> | ||
#include <pwd.h> | ||
#include "../uthash/uthash.h" //for the hash used in the sample module | ||
|
||
#ifdef __linux__ | ||
extern char *strptime(const char *, const char *, struct tm *); | ||
|
@@ -287,6 +288,19 @@ struct plugin { | |
}; | ||
LIST(struct plugin) plugins; | ||
|
||
typedef struct{ | ||
UT_hash_handle hh; //makes the structure hashable using "uthash/uthash.h" | ||
uint32_t from; //these next 5 fields make up the compound key | ||
int sport,dport,transaction_id; | ||
uint32_t to; | ||
}samplePacket ; | ||
|
||
typedef struct{ | ||
uint32_t from; | ||
int sport,dport,transaction_id; | ||
uint32_t to; | ||
}sample_lookup_key; | ||
|
||
/* Forward. */ | ||
|
||
static void setsig(int, int); | ||
|
@@ -384,6 +398,12 @@ static unsigned long long mem_limit = (unsigned) MEM_MAX; // process memory li | |
static int mem_limit_set = 1; // Should be configurable | ||
const char DROPTOUSER[] = "nobody"; | ||
static pcap_thread_t pcap_thread = PCAP_THREAD_T_INIT; | ||
static int sample = FALSE; | ||
static unsigned sampleAmount; | ||
static unsigned querycount; | ||
static samplePacket *allSampleQueries = NULL; | ||
static int chooseSidesResponse = FALSE; | ||
static unsigned keylen; | ||
|
||
/* Public. */ | ||
|
||
|
@@ -694,7 +714,8 @@ help_1(void) { | |
"\t[-w <base> [-W <suffix>] [-k <cmd>]] [-t <lim>] [-c <lim>] [-C <lim>]\n" | ||
"\t[-x <pat>]+ [-X <pat>]+\n" | ||
"\t[-B <datetime>] [-E <datetime>]\n" | ||
"\t[-P plugin.so] [-U <str>]\n", | ||
"\t[-P plugin.so] [-U <str>]\n" | ||
"\t[-q <nth>]\n", | ||
ProgramName); | ||
} | ||
|
||
|
@@ -755,6 +776,8 @@ help_2(void) { | |
"\t-E <datetime> end collecting at this date and time\n" | ||
"\t-M set monitor mode on interfaces\n" | ||
"\t-D set immediate mode on interfaces\n" | ||
"\t-q <nth> output only every nth DNS query and only output responses\n \ | ||
if they correspond to one of the sampled queries\n" | ||
); | ||
} | ||
|
||
|
@@ -782,7 +805,7 @@ parse_args(int argc, char *argv[]) { | |
INIT_LIST(myregexes); | ||
INIT_LIST(plugins); | ||
while ((ch = getopt(argc, argv, | ||
"a:bc:de:fgh:i:k:l:m:pr:s:t:u:w:x:" | ||
"a:bc:de:fgh:i:k:l:m:pq:r:s:t:u:w:x:" | ||
#ifdef USE_SECCOMP | ||
"y" | ||
#endif | ||
|
@@ -889,6 +912,7 @@ parse_args(int argc, char *argv[]) { | |
msg_wanted = u; | ||
break; | ||
case 's': | ||
chooseSidesResponse = TRUE; | ||
u = 0; | ||
for (p = optarg; *p; p++) | ||
switch (*p) { | ||
|
@@ -898,6 +922,13 @@ parse_args(int argc, char *argv[]) { | |
} | ||
dir_wanted = u; | ||
break; | ||
case 'q': | ||
sample = TRUE; | ||
sampleAmount = atoi(optarg); | ||
if(sampleAmount == 0) | ||
usage("-q takes only unsigned integer values != 0"); | ||
querycount = 0; | ||
break; | ||
case 'h': | ||
u = 0; | ||
for (p = optarg; *p; p++) | ||
|
@@ -1099,6 +1130,11 @@ parse_args(int argc, char *argv[]) { | |
usage("the -L and -l options are mutually exclusive"); | ||
if (background && (dumptrace || preso)) | ||
usage("the -b option is incompatible with -d and -g"); | ||
if (sample && chooseSidesResponse) | ||
{ | ||
if(((dir_wanted & DIR_RESPONSE) != 0) && ((dir_wanted & DIR_INITIATE) == 0)) | ||
usage("the -q option is incompatible with -s r"); | ||
} | ||
if (dumptrace >= 1) { | ||
endpoint_ptr ep; | ||
const char *sep; | ||
|
@@ -2339,8 +2375,60 @@ network_pkt(const char *descr, my_bpftimeval ts, unsigned pf, | |
abort(); | ||
} | ||
} | ||
output(descr, from, to, proto, flags, sport, dport, ts, | ||
pkt_copy, olen, dnspkt, dnslen); | ||
/*Sample Module*/ | ||
if (sample == TRUE) | ||
{ | ||
ns_msg dnsmsgSample; | ||
ns_initparse(dnspkt,dnslen,&dnsmsgSample); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is part of libbind and dnscap can be compiled without libbind. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Look at the top There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For now I'll disable the sampling code if libbind is missing. In future i might try to write my own parsing functions There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The sampling code is still compiled even if libbind does not exist, checking if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes but in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You do know the difference between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do and I just realized where my mistake in thinking was at. I will work on it right away. |
||
samplePacket *currentQuery; | ||
|
||
uint32_t *fromBuffer = (uint32_t*)&from.u; | ||
uint32_t *toBuffer = (uint32_t*)&to.u; | ||
|
||
keylen = offsetof(samplePacket,to) //keylen is used to define which fields of the hash structure are added | ||
+ sizeof(*toBuffer) //as a compound key. Here, the key is composed of all fields between (and including) | ||
- offsetof(samplePacket,from); //samplePacket->to and samplePacket->from (from, sport, dport, transaction_id, to) | ||
|
||
if(dns.qr == 0) | ||
{ | ||
querycount++; | ||
if(querycount % sampleAmount == 0) | ||
{ | ||
currentQuery = calloc(1,sizeof(*currentQuery)); | ||
assert(currentQuery != NULL); | ||
currentQuery->from = *fromBuffer; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are meant to be in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
On my system There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry you need to find a way to support both v4 and v6 otherwise I will reject the pull request. I do not know how exactly uthash works but maybe you can use the either There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I initially used In case I can't get it to work with IPv6 at all, I'll inform you, so you can reject this pull request. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Look at plugins/rssm/rssm.c for an example of how to make a hash table with both v4 and v6 addresses ("my_hashtbl"). dnscap_common.h defines 'iaddr' which you should use to store v4/v6 addrs. rssm.c (and other plugin .c files) have iaddr_hash(). At some point it would make sense to move hashtbl.c and supporting functions out of plugins and into src. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Found a way that will work perfectly fine. Ill commit it on Monday! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry but you have implemented this in a very dangerous way and the use of |
||
currentQuery->to = *toBuffer; | ||
currentQuery->sport = sport; | ||
currentQuery->dport = dport; | ||
currentQuery->transaction_id = ns_msg_id(dnsmsgSample); | ||
|
||
HASH_ADD(hh,allSampleQueries,from,keylen,currentQuery); | ||
output(descr,from,to,proto,flags,sport,dport,ts,pkt_copy,olen,dnspkt,dnslen); | ||
} | ||
} | ||
else | ||
{ | ||
sample_lookup_key *lookup_key = (sample_lookup_key*)calloc(1,sizeof(*lookup_key)); | ||
assert(lookup_key != NULL); | ||
lookup_key->from = *toBuffer; | ||
lookup_key->to = *fromBuffer; | ||
lookup_key->dport = sport; | ||
lookup_key->sport = dport; | ||
lookup_key->transaction_id = ns_msg_id(dnsmsgSample); | ||
|
||
HASH_FIND(hh,allSampleQueries,&lookup_key->from,keylen,currentQuery); | ||
if(currentQuery) | ||
{ | ||
HASH_DEL(allSampleQueries,currentQuery); | ||
free(currentQuery); | ||
output(descr,from,to,proto,flags,sport,dport,ts,pkt_copy,olen,dnspkt,dnslen); | ||
} | ||
free(lookup_key); | ||
} | ||
}else | ||
{ | ||
output(descr,from,to,proto,flags,sport,dport,ts,pkt_copy,olen,dnspkt,dnslen); | ||
} | ||
} | ||
|
||
/* | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second glance I do not see the reason to have
chooseSidesResponse
,dir_wanted
is set to both direction at start and you really only need to check ifDIR_RESPONSE
is not set.