dsc.conf(5)
πΈ dsc.conf β the whole vibe, explained πΈ
okay bestie, welcome to dsc.conf(5), aka the File Formats Manual page for dsc.conf. this is where you configure dsc, and i'm gonna walk you through every single line of it. no skips. no "you'll figure it out". we're going the whole way π
β¨ NAME β¨
dsc.conf β the configuration file for the DNS Statistics Collector. that's it, that's the name, adorable.
π DESCRIPTION π
so, dsc.conf holds the defaults for the program dsc(1). every single line is a configuration option, and it can take arguments shaped like option value;.
comment lines? those need a hash sign (#) in the first column. no sneaky indented comments, the # has to be all the way at the start or it's not a comment. periodt.
π¨ real talk: sincedsc(1)version 2.2.0, a configuration line may not be divided with CR/LF and quoted characters are not understood (\quote). so don't try it. the parser will simply not get it and you'll be sad.
π CONFIGURATION π
this is the main character section. every directive, in order, let's go π¦
local_address IP [ MASK / BITS ] ;β tells dsc the DNS server's local IP address, plus an optional mask/bits for local networks. it's used to figure out which direction an IP packet is going: sending, receiving, or other. you can repeat thelocal_addressline as many times as you want to specify multiple local addresses. πrun_dir PATH ;β a directory that becomes dsc's current directory once it starts. output files get written here, and so do any core dumps. yes, core dumps, don't ask.minfree_bytes BYTES ;β if the filesystem where dsc writes its output files doesn't have at least this much free space, then dsc will not write the files. this exists to keep dsc from absolutely devouring your filesystem. the files that would have been written are simply lost and cannot be recovered π. output files start being written again once the filesystem has the free space it needs. so like, it's a safety valve, not a rescue mission.pid_file " FILE " ;β the file where dsc stores its process id. classic.bpf_program " RULE " ;β a Berkeley Packet Filter program string. you can use this to further restrict the traffic seen, but heads up: dsc currently has one indexer that looks at all IP packets. if you specify something likeudp port 53, that indexer will not work.
that said β if you wanna monitor multiple DNS servers with separate dsc instances on one collector box, you may actually need bpf_program to make sure each dsc process only sees the traffic it's supposed to see. so it has its uses π
β οΈ this directive must go before the interface directive. why? because dsc makes only one pass through the configuration file, and the BPF filter is set when the interface is initialized. order matters, bestie.
dns_port NUMBER ;β dsc only parses traffic coming to or leaving the DNS port (default53), and this option lets you control which port that is, in case yours isn't standard.pcap_buffer_size NUMBER ;β sets the buffer size (in bytes) for pcap. bumping this up may help if you're seeing dropped packets by the kernel, but increasing it too much may have other side effects. balance is everything, it's giving skincare routine.
β οΈ this directive must go before the interface directive, because dsc makes only one pass through the config file and the pcap buffer size is set when the interface is initialized.
pcap_thread_timeout MILLISECONDS ;β sets the internal timeout pcap-thread uses when waiting for packets. default is100ms.
β οΈ this directive must go before the interface directive.
drop_ip_fragments ;β drops all packets that are fragments. bye bye fragments π
β οΈ this directive must go before the interface directive.
interface IFACE | FILE ;β the interface name to sniff packets from, or a pcap file to read packets from. you can specify multiple interfaces by repeating theinterfaceline as many times as you like.
under Linux (kernel v2.2+) libpcap can use an "any" interface which will include any interfaces the host has β but those interfaces will not be put into promiscuous mode, which may prevent capturing traffic that is not directly related to the host. iykyk.
dnstap_file FILE ;dnstap_unixsock FILE [ USER ][ :GROUP ] [ UMASK ] ;dnstap_tcp IP PORT ;dnstap_udp IP PORT ;β these specify DNSTAP input from a file, UNIX socket, UDP or TCP connections (dsc will listen for incoming connections). this type of input is delivered directly from the DNS software itself as encapsulated DNS packets, as seen or as made by the software. seehttps://dnstap.infofor more info about DNSTAP. π§
for UNIX sockets there are additional optional options to control access to it. the user and group access are specified together as strings (USER:GROUP), separated with a colon if a group is specified. the file permissions are controlled by a file mode creation mask (UMASK, must begin with 0) which is set temporarily during socket creation. you don't have to specify all of them β you can specify only USER, only :GROUP, or only UMASK.
the example below shows how to give read and write access to somegroup, remove permissions for others, and how the resulting socket file permissions would look:
dnstap_unixsock /path/to/file.sock :somegroup 0007;
srwxrwx--- 1 root somegroup 0 Date dd HH:MM /path/to/file.sock
NOTE: - Only one DNSTAP input can be specified at a time currently. - Configuration needs to match that of the DNS software.
dnstap_network IPV4 IPV6 PORT ;β specifies DNSTAP network information.
per the DNSTAP specification, some information may not be included, like the receiver or sender of DNS. to be able to produce statistics, dsc needs to know what to put in place when that information is missing. that's what dnstap_network configures β and it should be the primary IP addresses and port of the DNS software.
default values are 127.0.0.1 ::1 53. π
qname_filter NAME FILTER ;β this directive lets you define custom filters to match query names in DNS messages. go look at the QNAME FILTERS section for the details.datasets NAME TYPE LABEL:FIRST LABEL:SECOND FILTERS [ PARAMETERS ] ;β this directive is the heart of dsc. it is also the most complex (see the DATASETS section). main character energy fr fr.
see the EXAMPLE section for a set of defined good datasets, which is also installed as dsc.conf.sample. β¨
bpf_vlan_tag_byte_order TYPE ;β dsc knows about VLAN tags. some operating systems (FreeBSD-4.x) have a bug where the VLAN tag id is byte-swapped π. valid values for this directive arehostandnet(the default isnet). set it tohostif you suspect your OS has the VLAN tag byte order bug.match_vlan ID [ ID ... ] ;β a white-space separated list of VLAN identifiers. if you set it, only the packets belonging to these VLANs are analyzed.statistics_interval SECONDS ;β how often dsc should write statistics. defaults to60seconds.no_wait_interval ;β don't wait on interval sync to start capturing. normally DSC will sleep fortime() % statistics_intervalto align with the minute (as was the default interval before), but now if you change the interval to more than a minute you can use this option to begin capture right away. πβοΈoutput_format FORMAT ;β the output format. you may specify multiple formats by repeating theoutput_formatline any number of times. default output format is XML β see the DATA FORMATS and FILE NAMING CONVENTIONS sections.output_user USER ;β which user should own the output file. defaults to the user running dsc.output_group GROUP ;β which group should own the output file. defaults to the group of the user running dsc.output_mod FILE_MODE_BITS ;β the file mode bits (in octal) for the output file permissions. defaults to0664.dump_reports_on_exit ;β dumps any remaining report before exiting.
NOTE: Timing in the data files will be off! β°
geoip_v4_dat " FILE " [ OPTION ... ] ;β the GeoIP dat file to open for IPv4 country lookup. see the GEOIP section for options.geoip_v6_dat " FILE " [ OPTION ... ] ;β the GeoIP dat file to open for IPv6 country lookup. see the GEOIP section for options.geoip_asn_v4_dat " FILE " [ OPTION ... ] ;β the GeoIP dat file to open for IPv4 AS number lookup. see the GEOIP section for options.geoip_asn_v6_dat " FILE " [ OPTION ... ] ;β the GeoIP dat file to open for IPv6 AS number lookup. see the GEOIP section for options.asn_indexer_backend BACKEND ;β what backend to use for the ASN indexer. either"geoip"for GeoIP Legacy or"maxminddb"for MaxMind DB (GeoIP2).country_indexer_backend BACKEND ;β what backend to use for the country indexer. either"geoip"for GeoIP Legacy or"maxminddb"for MaxMind DB (GeoIP2).maxminddb_asn " FILE " ;β the MaxMind DB file to use for ASN lookups.maxminddb_country " FILE " ;β the MaxMind DB file to use for country lookups.client_v4_mask NETMASK ;β sets the IPv4MASKforclient_subnetINDEXERS.client_v6_mask NETMASK ;β sets the IPv6MASKforclient_subnetINDEXERS.response_time_mode MODE ;β sets the outputMODEof the response time indexer:bucketβ count response time in buckets of microseconds. seeresponse_time_bucket_sizefor setting the size of the buckets.log10β count response time in logarithmic scale with base 10.log2β count response time in logarithmic scale with base 2.
response_time_max_queries NUMBER ;β sets the maximum number of queries to keep track of.response_time_full_mode MODE ;β if the number of queries tracked exceedsresponse_time_max_queries, theMODEcontrols how to handle it:drop_queryβ drop the incoming query.drop_oldestβ drop the oldest query being tracked and accept the incoming one.
response_time_max_seconds SECONDS ;β sets the maximum seconds to keep a query. but a query can still be matched to a response while being outside this limit β seeresponse_time_max_sec_modefor how those situations are handled.response_time_max_sec_mode MODE ;β controls how to handle queries and responses which are matched successfully but exceedresponse_time_max_seconds:ceilβ the query will be counted as successful, but the time it took will be the maximum seconds (think ceiling, orceil()).timed_outβ the query will be counted as timed out.
response_time_bucket_size SIZE ;β okay so this controls the size of the bucket in bucket mode, and the unit is microseconds. periodtknowntlds_file FILE ;β loads known TLDs fromFILE. It should be, or have the same format as,https://data.iana.org/TLD/tlds-alpha-by-domain.txt. π¦tld_list FILE ;β this one changes what DSC considers a TLD (similar to a Public Suffix List) and affects any indexers that gather statistics on TLDs, such as thetld,second_ldandthird_ldindexers. The file format is simply one line per suffix, and it supports commenting out lines with#. You can usedsc-psl-convertto convert the Public Suffix List to this format β seedsc-psl-convert(5)for more information and examples on how to set it up. iykyk π
π¦ DATASETS π¦
A dataset is a 2-D array of counters. For example, you might have a dataset with βQuery Typeβ along one dimension and βQuery Name Lengthβ on the other. The result is a table that shows the distribution of query name lengths for each query type. no cap β¨
A dataset has the following format:
datasets NAME TYPE LABEL:FIRST LABEL:SECOND FILTERS [ PARAMETERS ] ;
NAMEβ the name of the dataset. This must be unique, and it's used in the filename for the output files. main character energyTYPEβ the protocol layer. Available layers are:ipdns
LABELβ the label of the dimensions.FIRSTβ the indexer for the first dimension, see INDEXERS sections.SECONDβ the indexer for the second dimension, see INDEXERS sections.FILTERSβ one or more filters, see FILTERS sections.PARAMETERSβ zero or more parameters, see section PARAMETERS.
β¨ INDEXERS AND FILTERS β¨
An indexer is simply a function that transforms the attributes of an IP/DNS message into an array index. For some attributes the transformation is straightforward. For example, the βQuery Typeβ indexer simply extracts the query type value from a DNS message and uses this 16-bit value as the array index. it's giving simple π
Other attributes are slightly more complicated. For example, the βTLDβ indexer extracts the TLD of the QNAME field of a DNS message and maps it to an integer. The indexer maintains a simple internal table of TLD-to-integer mappings. The actual integer values are unimportant because the TLD strings, not the integers, appear in the resulting data. the way that works π₯
When you specify an indexer on a dataset line, you must provide both the name of the indexer and a label. The Label appears as an attribute in the output. <emojis>π</emojis>
For example the following line:
dataset the_dataset dns Foo:foo Bar:bar queries-only;
Would produce the following XML output:
<array name="the_dataset" dimensions="2" start_time="1091663940" ...
<dimension number="1" type="Foo"/>
<dimension number="2" type="Bar"/>
<data>
<Foo val="1">
<Bar val="0" count="4"/>
...
<Bar val="100" count="41"/>
</Foo>
<Foo val="2">
...
</Foo>
</data>
</array>
π IP INDEXERS π
dsc includes only minimal support for collecting IP-layer stats. Mostly we are interested in finding out the mix of IP protocols received by the DNS server. It can also show us if/when the DNS server is the subject of a denial-of-service attack. protect the queen π
ip_directionβ one of three values:sent,recvorelse. Direction is determined based on the setting forlocal_addressin the configuration file. which way did they go π§ip_protoβ the IP protocol type, e.g.:tcp,udporicmp. Note that thebpf_programsetting affects all traffic seen. If the program contains the wordudpthen you won't see any counts for non-UDP traffic. blocked and bopped πip_versionβ the IP version number, e.g.:4or6. Can be used to compare how much traffic comes in via IPv6 compared to IPv4. π
π IP FILTERS π
Currently there is only one IP protocol filter: any. It includes all received packets. that's it, that's the filter π
certain_qnamesβ this one β¨isolatesβ¨ the two most iconic query names the DNS root servers keep seeing:localhostand[a--m].root-servers.net. That's it, that's the whole vibe.client_subnetβ groups DNS messages together by the subnet of the client's IP address. The subnet gets masked by/24for IPv4 and by/96for IPv6. We use this to make datasets with big, diverse client populations way more manageable, and also to hand out a tiny lil bit of privacy and anonymization π«Ά.clientβ the IP (v4 and v6) address of the DNS client.serverβ the IP (v4 and v6) address of the DNS server.countryβ the country code of the IP (v4 and v6), see section GEOIP.asnβ the AS (autonomous system) number of the IP (v4 and v6), see section GEOIP.do_bitβ this indexer only has two values:0or1. It tells you whether or not the "DO" bit is set in a DNS query. Per RFC 2335: setting the DO bit to one in a query tells the server the resolver can accept DNSSEC security RRs. slay πedns_versionβ the EDNS version number, if there even is one, in a DNS query. EDNS Version 0 is documented in RFC 2671.edns_bufsizβ the EDNS buffer size per 512 chunks (0-511,512-1023etc).edns_cookieβ tells you whether or not an EDNS(0) Cookie (RFC7873) was present, with"yes"or"no".edns_cookie_lenβ the combined length of the EDNS(0) client and server cookies.edns_cookie_clientβ the EDNS(0) Client Cookie bytes as a hexadecimal string.edns_cookie_serverβ the EDNS(0) Server Cookie bytes as a hexadecimal string.edns_ecsβ tells you whether or not an EDNS(0) Client Subnet (RFC7871) was present, with"yes"or"no".edns_ecs_familyβ the EDNS(0) Client Subnet address family.edns_ecs_source_prefixβ the EDNS(0) Client Subnet source prefix-length.edns_ecs_scope_prefixβ the EDNS(0) Client Subnet scope prefix-length.edns_ecs_addressβ the EDNS(0) Client Subnet address bytes as a hexadecimal string.edns_ecs_subnetβ the EDNS(0) Client Subnet address as an IPv4/IPv6 textual address.edns_edeβ tells you whether or not an EDNS(0) Extended DNS Errors (RFC8914) was present, with"yes"or"no".edns_ede_codeβ the EDNS(0) Extended DNS Errors code.edns_ede_textlenβ the length of the EDNS(0) Extended DNS Errors extra-text.edns_ede_textβ the EDNS(0) Extended DNS Errors extra-text.edns_nsidβ tells you whether or not an EDNS(0) DNS Name Server Identifier (RFC5001) was present, with"yes"or"no".edns_nsid_lenβ the length of the EDNS(0) DNS Name Server Identifier (NSID).edns_nsid_dataβ the EDNS(0) DNS Name Server Identifier (NSID) bytes as a hexadecimal string.edns_nsid_textβ the EDNS(0) DNS Name Server Identifier (NSID) as a string of printable characters. Unprintable characters get replaced with".".idn_qnameβ this indexer only has two values:0or1. It returns1when the first QNAME in the DNS message question section is an internationalized domain name (i.e., containing non-ASCII characters). Those QNAMEs begin with the stringxn--. This convention is documented in RFC 3490.msglenβ the overall length (size) of the DNS message.nullβ a "no-op" indexer that always returns the same value. This can be used to effectively turn the 2-D table into a 1-D array. iconic β¨opcodeβ the DNS message opcode is a four-bit field.QUERYis the most common opcode. Additional currently defined opcodes include:IQUERY,STATUS,NOTIFY, andUPDATE.qclassβ the DNS message query class (QCLASS) is a 16-bit value.INis the most common query class. Additional currently defined query class values include:CHAOS,HS,NONE, andANY.qnameβ the full QNAME string from the first (and usually only) QNAME in the question section of a DNS message.qnamelenβ the length of the first (and usually only) QNAME in a DNS message question section. Note this is the "expanded" length if the message happens to take advantage of DNS message "compression".label_countβ the number of labels (between"."dots) in the first (and usually only) QNAME in a DNS message question section. Note that a value of0(zero) means DNS root (.).qtypeβ the query type (QTYPE) for the first QNAME in the DNS message question section. Well-known query types include:A,AAAA,A6,CNAME,PTR,MX,NS,SOA, andANY.query_classificationβ a stateless classification of "bogus" queries π:non-auth-tldβ when the TLD is not one of the IANA-approved TLDs.root-servers.netβ a query for a root server IP address.localhostβ a query for the localhost IP address.a-for-rootβ an"A"query for the DNS root (.).a-for-aβ an"A"query for an IPv4 address.rfc1918-ptrβ a PTR query for an RFC 1918 address.funny-classβ a query with an unknown/undefined query class, based on IANA DNS parameters.funny-qtypeβ a query with an unknown/undefined query type, based on IANA DNS parameters.src-port-zeroβ when the UDP message's source port equals zero.malformedβ a malformed DNS message that could not be entirely parsed.
rcodeβ the RCODE value in a DNS response. The most common response codes are0(NO ERROR) and3(NXDOMAIN).rd_bitβ this indexer returns1if the RD (recursion desired) bit is set in the query. Usually only stub resolvers set the RD bit. Usually authoritative servers do not offer recursion to their clients.tc_bitβ this indexer returns1if the TC (truncated) bit is set (in a response). An authoritative server sets the TC bit when the entire response won't fit into a UDP message.tldβ the TLD of the first QNAME in a DNS message's question section.second_ldβ the Second LD of the first QNAME in a DNS message's question section.third_ldβ the Third LD of the first QNAME in a DNS message's question section.transportβ tells you whether the DNS message is carried via UDP or TCP.dns_ip_versionβ the IP version number that carried the DNS message.dns_source_portβ the source port of the DNS message.dns_sport_rangeβ the source port of the DNS message per 1024 chunks (0-1023,1024-2047etc).qr_aa_bitsβ the"qr_aa_bits"dataset may be useful when dsc is monitoring an authoritative name server. This dataset counts the number of DNS messages received with each combination of QR,AA bits. Normally the authoritative name server should receive only queries. If the name server is the target of a DNS reflection attack, it will probably receive DNS responses which have the QR bit set. bestie if you see this blowing up, something is Not Okay πresponse_timeβ an indexer to track queries and return the response time in buckets along with other state buckets for timeouts, missing queries (received a response but have never seen the query), dropped queries (due to memory limitations) and internal errors. Queries are matched against responses by checking (in this order) the DNS ID, the IP version and protocol, client IP, client port, server IP and last server port. There are a few configuration options to control how response time statistics are gathered and handled, please see CONFIGURATION. NOTE: Only one instance of this indexer can be used in a dataset, this is due to the state it stores and the design of DSC.encryptionβ tells you whether the DNS message was carried over an encrypted connection or not, and if so over which. For example"unencrypted","dot"(DNS-over-TLS),"doh"(DNS-over-HTTPS). This information is only available via DNSTAP and if supported by the software generating it.
π DNS FILTERS π
You must specify one or more of the following filters (separated by commas) on the dataset line. Heads up bestie: multiple filters are ANDed together. That is, they narrow the input stream, rather than broaden it. So stack them and you get a smaller, more specific pile, not a bigger one π
anyβ the no-op filter, counts all messages.queries-onlyβ count only DNS query messages. A query is a DNS message where the QR bit is set to0.replies-onlyβ count only DNS response messages. A response is a DNS message where the QR bit is set to1.nxdomains-onlyβ count only NXDOMAIN responses.popular-qtypesβ count only DNS messages where the query type is one of:A,NS,CNAME,SOA,PTR,MX,AAAA,A6,ANY.idn-onlyβ count only DNS messages where the query name is in the internationalized domain name format.aaaa-or-a6-onlyβ count only DNS messages where the query type isAAAAorA6.root-servers-net-onlyβ count only DNS messages where the query name is within theroot-servers.netdomain.chaos-classβ counts only DNS messages where QCLASS is equal toCHAOS(3). The CHAOS class is generally used for only the specialhostname.bindandversion.bindqueries.priming-queryβ count only DNS messages where the query type isNSand QNAME is".".servfail-onlyβ count only SERVFAIL responses.authentic-data-onlyβ count only DNS messages with the AD bit is set.edns0-onlyβ count only DNS messages with EDNS(0) options.edns0-cookie-onlyβ count only DNS messages with EDNS(0) Cookie option.edns0-nsid-onlyβ count only DNS messages with EDNS(0) DNS Name Server Identifier option.edns0-ede-onlyβ count only DNS messages with EDNS(0) Extended DNS Errors option.edns0-ecs-onlyβ count only DNS messages with EDNS(0) Client Subnet option.
π QNAME FILTERS π
This is where you build your own custom QNAME-based filter for DNS messages β¨. If you refer to this named filter on a dataset line, then only queries or replies for matching QNAMEs will be counted. The QNAME argument is a regular expression. For example:
qname_filter WWW-Only ^www. ;
dataset qtype dns All:null Qtype:qtype queries-only,WWW-Only ;
no cap, that's the whole thing β name it, regex it, drop it on the dataset line, done π¦
β¨ PARAMETERS β¨
so dsc has these optional parameters you can turn on, and ngl they're the main character when it comes to keeping your datasets from getting THICC π
min-count=NNβ cells with counts less than NN get yeeted from the output entirely. instead of deleting them into the void, they get aggregated into the special values-:SKIPPED:-and-:SKIPPED_SUM:-. this is the move when your dataset has a million tiny little counts and you want it to be smaller. obsessed with this one honestly.max-cells=NNβ a different way to cap dataset size, and lowkey maybe the better one? π«Ά instead of standing there guessing whatmin-countvalue would be appropriate in advance,max-cellsjust puts a hard limit on the number of cells included for the second dimension of the dataset. so like, if your dataset has 9 possible first-dimension values and you saymax-cells=100, the dataset won't have more than 900 total values, periodt. the cell values get sorted and the top max-cell values are the ones that make it out. anything below that limit gets aggregated into the special-:SKIPPED:-and-:SKIPPED_SUM:-entries. slay.
π FILE NAMING CONVENTIONS π
the filename format is literally this:
${timestamp}.dscdata.${format}
for example:
1154649660.dscdata.xml
i know. iconic. no notes.
π DATA FORMATS π
XML π
a dataset XML file has this structure, bestie, read it carefully:
<array name="dataset-name" dimensions="2" start_time="unix-seconds"
stop_time="unix-seconds">
<dimension number="1" type="Label1"/>
<dimension number="2" type="Label2"/>
<data>
<Label1 val="D1-V1">
<Label2 val="D2-V1" count="N1"/>
<Label2 val="D2-V2" count="N2"/>
<Label2 val="D2-V3" count="N3"/>
</Label1>
<Label1 val="D1-V2">
<Label2 val="D2-V1" count="N1"/>
<Label2 val="D2-V2" count="N2"/>
<Label2 val="D2-V3" count="N3"/>
</Label1>
</data>
</array>
JSON β¨
a dataset JSON file has this structure:
{
"name": "dataset-name",
"start_time": unix-seconds,
"stop_time": unix-seconds,
"dimensions": [ "Label1", "Label2" ],
"data": [
{
"Label1": "D1-V1",
"Label2": [
{ "val": "D2-V1", "count": N1 },
{ "val": "D2-V2", "count": N2 },
{ "val": "D2-V3", "count": N3 }
]
},
{
"Label1": "D1-V2-base64",
"base64": true,
"Label2": [
{ "val": "D2-V1", "count": N1 },
{ "val": "D2-V2-base64", "base64": true, "count": N2 },
{ "val": "D2-V3", "count": N3 }
]
}
]
}
okay so decoding time π
dataset-name, Label1, and Label2 all come straight from the dataset definition. they're not vibes, they're config.
the start_time and stop_time attributes are given in Unix seconds, and they're normally 60 seconds apart. dsc usually kicks off a new measurement interval right on the 60 second boundaries. like this:
stop_time mod{60} == 0
the Label1 attributes (D1-V1, D1-V2) are values for the first dimension indexer. same situation with the Label2 attributes (D2-V1, D2-V2, D2-V3) β those are values for the second dimension indexer. for some indexers these values are numeric, for others they're strings, no drama. but if the value contains certain non-printable characters, the string gets base64-encoded and the optional BASE64 attribute is set to 1/true. π
there are two special vals that keep big datasets from being absolute units: -:SKIPPED:- and -:SKIPPED_SUM:-. these can show up on datasets that use the min-count and max-cells parameters (go look at the PARAMETERS section, i'll wait π«Ά). -:SKIPPED:- is the number of cells that did not get included in the output. -:SKIPPED_SUM:- is the sum of the counts for alllll the skipped cells.
heads up queen: "one-dimensional datasets" still use two dimensions in the output. the first dimension type and value will literally be All, like the example below:
<array name="rcode" dimensions="2" start_time="1154649600"
stop_time="1154649660">
<dimension number="1" type="All"/>
<dimension number="2" type="Rcode"/>
<data>
<All val="ALL">
<Rcode val="0" count="70945"/>
<Rcode val="3" count="50586"/>
<Rcode val="4" count="121"/>
<Rcode val="1" count="56"/>
<Rcode val="5" count="44"/>
</All>
</data>
</array>
the count values are always integers, no decimals ever. and if the count for a particular tuple is zero, it just shouldn't be in the output at all. if you see a zero bestie, something's wrong. π
also, the contents of the output do not tell you where it came from. the server and the node it came from are simply not present. it's giving mystery, it's giving anonymous, it's giving you-better-know-which-box-this-was.
π¦ GEOIP π¦
country code and AS number lookup is available using the MaxMind GeoIP Legacy API, but only if it was enabled during compilation. so like, if your build didn't have it, it's not happening, sorry bestie. π
you can give multiple options to the database and they map directly to the options for GeoIP_open(), just without the GEOIP_ prefix. example:
geoip_v4_dat "/usr/local/share/GeoIP/GeoIP.dat" STANDARD MEMORY_CACHE;
geoip_asn_v6_dat "/usr/local/share/GeoIP/GeoIPASNumv6.dat" MEMORY_CACHE;
per the GeoIP documentation, here's what those options do:
STANDARDβ read the database from the file system. this uses the least memory.MEMORY_CACHEβ load the database into memory. faster performance, but it eats more memory. tradeoffs, we hate to see it.CHECK_CACHEβ check for an updated database. if the database has been updated, reload the file handle and/or memory cache.INDEX_CACHEβ cache only the most frequently accessed index portion of the database. that gives you faster lookups thanGEOIP_STANDARD, but less memory usage thanGEOIP_MEMORY_CACHE. super useful for larger databases like GeoIP Legacy Organization and GeoIP Legacy City. β οΈ note: for GeoIP Legacy Country, Region and Netspeed databases,GEOIP_INDEX_CACHEis equivalent toGEOIP_MEMORY_CACHE. same energy.MMAP_CACHEβ load the database into mmap shared memory. MMAP is not available for 32bit Windows. so jot that down. π
π EXAMPLE π
here's the whole thing in all its glory, copy-paste energy, every line preserved:
local_address 127.0.0.1;
local_address ::1;
#local_address 127.0.0.0 255.0.0.0;
#local_address 192.168.0.0 24;
#local_address 10.0.0.0 8;
run_dir "/var/lib/dsc";
minfree_bytes 5000000;
pid_file "/run/dsc.pid";
# Example filters
#
#bpf_program "udp port 53";
#bpf_program "tcp port 53 or udp port 53";
# Use this to see only DNS *queries*
#
#bpf_program "udp dst port 53 and udp[10:2] & 0x8000 = 0";
#dns_port 53;
#pcap_buffer_size 4194304;
#pcap_thread_timeout 100;
#drop_ip_fragments;
interface eth0;
#interface any;
#dnstap_file /path/to/file.dnstap;
#dnstap_unixsock /path/to/unix.sock;
#dnstap_tcp 127.0.0.1 5353;
#dnstap_udp 127.0.0.1 5353;
#dnstap_network 127.0.0.1 ::1 53;
dataset qtype dns All:null Qtype:qtype queries-only;
dataset rcode dns All:null Rcode:rcode replies-only;
dataset opcode dns All:null Opcode:opcode queries-only;
dataset rcode_vs_replylen dns Rcode:rcode ReplyLen:msglen replies-only;
dataset client_subnet dns All:null ClientSubnet:client_subnet queries-only max-cells=200;
dataset qtype_vs_qnamelen dns Qtype:qtype QnameLen:qnamelen queries-only;
dataset qtype_vs_tld dns Qtype:qtype TLD:tld queries-only,popular-qtypes max-cells=200;
dataset certain_qnames_vs_qtype dns CertainQnames:certain_qnames Qtype:qtype queries-only;
dataset client_subnet2 dns Class:query_classification ClientSubnet:client_subnet queries-only max-cells=200;
dataset client_addr_vs_rcode dns Rcode:rcode ClientAddr:client replies-only max-cells=50;
dataset chaos_types_and_names dns Qtype:qtype Qname:qname chaos-class,queries-only;
#dataset country_code dns All:null CountryCode:country queries-only;
#dataset asn_all dns IPVersion:dns_ip_version ASN:asn queries-only max-cells=200;
dataset idn_qname dns All:null IDNQname:idn_qname queries-only;
dataset edns_version dns All:null EDNSVersion:edns_version queries-only;
dataset edns_bufsiz dns All:null EDNSBufSiz:edns_bufsiz queries-only;
dataset do_bit dns All:null D0:do_bit queries-only;
dataset rd_bit dns All:null RD:rd_bit queries-only;
dataset idn_vs_tld dns All:null TLD:tld queries-only,idn-only;
dataset ipv6_rsn_abusers dns All:null ClientAddr:client queries-only,aaaa-or-a6-only,root-servers-net-only max-cells=50;
dataset transport_vs_qtype dns Transport:transport Qtype:qtype queries-only;
dataset client_port_range dns All:null PortRange:dns_sport_range queries-only;
#dataset second_ld_vs_rcode dns Rcode:rcode SecondLD:second_ld replies-only max-cells=50;
#dataset third_ld_vs_rcode dns Rcode:rcode ThirdLD:third_ld replies-only max-cells=50;
dataset direction_vs_ipproto ip Direction:ip_direction IPProto:ip_proto any;
#dataset dns_ip_version_vs_qtype dns IPVersion:dns_ip_version Qtype:qtype queries-only;
#dataset response_time dns All:null ResponseTime:response_time;
#dataset priming_queries dns Transport:transport EDNSBufSiz:edns_bufsiz priming-query,queries-only;
#dataset priming_responses dns All:null ReplyLen:msglen priming-query,replies-only;
#dataset qr_aa_bits dns Direction:ip_direction QRAABits:qr_aa_bits any;
#dataset servfail_qname dns ALL:null Qname:qname servfail-only,replies-only;
#dataset ad_qname dns ALL:null Qname:qname authentic-data-only,replies-only;
#dataset label_count dns All:null LabelCount:label_count any;
#dataset encryption dns All:null Encryption:encryption queries-only;
#statistics_interval 60;
#no_wait_interval;
output_format XML;
#output_format JSON;
#output_user root;
#output_group root;
#output_mod 0664;
#geoip_v4_dat "/usr/share/GeoIP/GeoIP.dat" STANDARD MEMORY_CACHE MMAP_CACHE;
#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;
#asn_indexer_backend geoip;
#country_indexer_backend geoip;
#maxminddb_asn "/path/to/GeoLite2/ASN.mmdb";
#maxminddb_country "/path/to/GeoLite2/Country.mmdb";
#client_v4_mask 255.255.255.0;
#client_v6_mask ffff:ffff:ffff:ffff:ffff:ffff:0000:0000;
#response_time_mode log10;
#response_time_max_queries 1000000;
#response_time_full_mode drop_query;
#response_time_max_seconds 5;
#response_time_max_sec_mode ceil;
#response_time_bucket_size 100;
#knowntlds_file file;
like. a whole config. in one code block. we ate. π
π FILES π
/etc/dsc/dsc.conf/etc/dsc/dsc.conf.sample
those are the two paths, that's the whole list, don't @ me.
π SEE ALSO π
go read those too bestie, they're right there. iykyk. π§
π AUTHORS π
- Jerry LundstrΓΆm, DNS-OARC
- Duane Wessels, Measurement Factory / Verisign
- Ken Keys, Cooperative Association for Internet Data Analysis
- Sebastian Castro, New Zealand Registry Services
maintained by DNS-OARC
https://www.dns-oarc.net/tools/dsc
the whole squad built this. literal kings. π
π BUGS π
for issues and feature requests please use:
https://codeberg.org/DNS-OARC/dsc/issues
for question and help please use:
admin@dns-oarc.net
(yeah it says "question" not "questions", i'm keeping it exactly as written, no cap π )
okay bestie that's the whole page!! π this was DNS Statistics Collector, version 2.16.1, and you just survived the entirety of dsc.conf(5). go forth and configure your datasets, you absolute icon, and remember: every flag, every option, every default was preserved exactly, because we keep the facts and change only the vibe. mwah. πβ¨π¦
π¦ where this page comes from
- ubuntu stonking: oarc-dsc 2.16.1-1 Β· BSD-3-Clause
- Copyright (c) 2008-2026 OARC, Inc
- Copyright (c) 2007-2008, Internet Systems Consortium, Inc
- Copyright (c) 2003-2007, The Measurement Factory, Inc
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms