-
-
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 4 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 |
---|---|---|
|
@@ -53,6 +53,7 @@ | |
.Op Fl E Ar datetime | ||
.Op Fl P Ar plugin.so | ||
.Op Fl U Ar str | ||
.Op Fl q Ar unsigned int | ||
.Sh DESCRIPTION | ||
.Nm | ||
is a network capture utility designed specifically for DNS traffic. It | ||
|
@@ -353,6 +354,11 @@ Enable immediate mode on interfaces. | |
Append "and | ||
.Ar str | ||
" to the pcap filter. | ||
.It Fl q Ar unsigned int | ||
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. Same here. 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 see, I'll change it! |
||
Causes the output to be sampled after the application of all other filters. | ||
Only every nth dns initiation will be output and responses are only output | ||
if they correspond to one of the sampled queries. This option cannot be | ||
used with option. | ||
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. Last sentence is unclear, specify the options that can't be used. 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'm very sorry, this must have been a copy and paste error. The last sentence is only half of the sentence it should be, I'll correct that. |
||
.El | ||
.Pp | ||
If started with no options, | ||
|
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" | ||
unsigned from; //these next 5 fields make up the compound key | ||
int sport,dport,transaction_id; | ||
unsigned to; | ||
}samplePacket ; | ||
|
||
typedef struct{ | ||
unsigned from; | ||
int sport,dport,transaction_id; | ||
unsigned 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 <unsinged int>]\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 <unsigned int> 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_INITIATE) != 0) && ((dir_wanted & DIR_RESPONSE) != 0)) | ||
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. Why check this? If both are true then both options have been used. 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. It should be incompatible with -s r. I fixed this flaw. |
||
usage("the -q option is incompatible with -s r"); | ||
} | ||
if (dumptrace >= 1) { | ||
endpoint_ptr ep; | ||
const char *sep; | ||
|
@@ -2339,8 +2375,61 @@ 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; | ||
void *ipAddrBufferFrom = &from.u; | ||
void *ipAddrBufferTo = &to.u; | ||
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. There is no need for these 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. Oh okay, I initially tried to cast it in one go, but i got a compiler error. Ill try again, thank you! |
||
unsigned *fromBuffer = (unsigned*)ipAddrBufferFrom; | ||
unsigned *toBuffer = (unsigned*)ipAddrBufferTo; | ||
|
||
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 = malloc(sizeof(*currentQuery)); | ||
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 not check 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. Mhm okay, thank you! I'll add all malloc checks that need to be added. |
||
memset(currentQuery, 0, sizeof(*currentQuery)); | ||
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*)malloc(sizeof(*lookup_key));; | ||
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 not check 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. Mhm okay, thank you! I'll add all malloc checks that need to be added. 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 see, i should also you 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, one |
||
memset(lookup_key, 0, sizeof(*lookup_key)); | ||
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.
The phrasing
unsigned int
is not very user friendly, use something likenth
instead.