dstore-dist
Root Node Config¶
A minimal dstore-dist configuration (missing the details of the destination and route configuration) could be:
listen:
- "127.0.0.1:2000"
- "[::1]:2000"
tls_listen:
- addr: "127.0.0.1:2001"
tlsconfig:
cert_file: /etc/certs/cert.pem
key_file: /etc/certs/cert.key
log:
level: Warn
ipsets:
ipset1:
file: /etc/ipset1.txt
poll_interval: 10s
destinations:
mydestination1:
<destination configuration>
mydestination2:
<destination configuration>
routes:
myroute1:
<route configuration>
myroute2:
<route configuration>
The following YAML key-values are supported for configuration at the root node:
| Parameter | Type | Default | Description |
|---|---|---|---|
batch_buffer_size |
int |
1048576 | The size in bytes of the buffer(s) used to batch messages internally. Normally the default of 1048576 (1MB) will suffice, but when using Kafka, making this value around 90% of the value of the kafka max_msg_size is a good idea, to avoid fragmentation of the messages when sending to Kafka. |
conn_timeout |
go:DurationString |
The idle timeout for incoming connections to dstore-dist. Defaults to no timeout, i,e. only applies if explicitly configured. | |
debug |
boolean |
false | Enable/disable very verbose debug logging |
destinations |
Map of Destination | Each map key is the name of a destination, and the value is a Destination | |
history_num_batches |
int |
Number of batches to keep in memory for the history API. A batch is capped at 1 MB by default, see batch_buffer_size for the actual size. If this is unset or set to 0, the history API is disabled. The history API can be accessed at /api/history. By default this URL will print additional usage information, including how to switch to Protobuf or JSON output format, and how to filter on certain fields. |
|
http_address |
string |
Listen address for HTTP webserver for Prometheus metrics and status page. Value is an address:port string, using the same format as for listen addresses. |
|
http_api_key |
string |
If set, an X-API-Key header matching this key is required to access the optional HTTP history API. |
|
input_framing |
string |
16bit |
Controls whether to expect 16-bit or 32-bit length prefixes for incoming protobuf messages. Valid values are 16bit and 32bit. |
ipsets |
Map of IP Set | ||
listen |
List of string |
The addresses that dstore-dist will listen on for new protobuf messages. The value is a list of address:port strings, in either v4 or v6 format. IPv6 addresses must be placed in square brackets like this [::1]. You can omit the address to listen on all local addresses. |
|
log |
Log Config | ||
routes |
Map of Route | Each map key is the name of a route, and the value is a Route | |
tls_listen |
List of TLS Listen | The addresses that dstore-dist will listen on for new protobuf messages. The value is a list of address:port strings, in either v4 or v6 format. IPv6 addresses must be placed in square brackets like this [::1]. You can omit the address to listen on all local addresses. |
A note on the input_framing parameter:
- Protobuf messages sent and received by dstore components contain a length prefix so that the length of each message can be determined and read safely.
- Historically PowerDNS processes have emitted protobuf messages with a 16-bit length prefix.
- Due to the increasing amount of data in the protobuf message, including data such as Open Telemetry, there is a small chance that the 16-bit prefix will not be enough to hold the entire message.
- Thus PowerDNS products such as recursor, authoritative, and dnsdist either support or will support the capability to emit 32-bit length prefixes.
- The
dstore-distinput framing parameter allows you to control whether to expect 16-bit or 32-bit length prefixes. However note that this is a global switch that applies to all input, i.e. it is not possible to accept mixed input streams of 16-bit and 32-bit length prefixes. Thus you should ensure that all processes that send data to dstore-dist are using the same prefix length, whether that is 16-bit or 32-bit. - Similarly the other applications in dstore that process protobuf: topn-reporter and eventforwarder can be configured to
accept 32-bit length prefixes. Note that
dstore-distenables protobuf sent out to be "upgraded" from 16-bit to 32-bit, but it is not possible to downgrade from 32-bit to 16-bit prefixes (because data may be lost).
Log Config¶
Log Configuration is as follows:
| Parameter | Type | Default | Description |
|---|---|---|---|
level |
string |
Defaults to Info. Can also be set to Warn, Error, Debug or Trace. For debug level to take effect, the -debug flag must also be set. |
|
stdout |
boolean |
false |
By default logging will go to stderr, set this to true send to stdout instead. |
text |
boolean |
false |
If true, enable text-based logging. The default is JSON logging. |
TLS Listen¶
You can configure a TLS Listener as follows:
| Parameter | Type | Default | Description |
|---|---|---|---|
addr |
string |
The address:port to listen on | |
tlsconfig |
TLS Config | Configuration of TLS parameters |
TLS Config¶
| Parameter | Type | Default | Description |
|---|---|---|---|
insecure_skip_verify |
boolean |
false |
Controls whether a client verifies the server's certificate chain and hostname. |
ca_file |
string |
Optional CA file to use (PEM). | |
ca |
string |
Optional CA to use specified as a string in PEM format. | |
add_system_ca_pool |
boolean |
false |
Adds the system CA pool if private CAs are enabled, when set. |
cert_file |
string |
Optional certificate file to use (PEM). | |
cert |
string |
Optional certificate to use specified as a string in PEM format. | |
key_file |
string |
Optional key file to use (PEM). | |
key |
string |
Optional key to use specified as a string in PEM format. | |
require_client_cert |
boolean |
false |
Controls whether a client certificate is required (MTLS). ca must be set if this is true. |
watch_certs |
boolean |
false |
If true, enables background reloading of certifcate files. |
watch_certs_poll_interval |
go:DurationString |
5s |
If watch_certs is true, how often to check for changes. |
IPSet¶
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
file |
string |
yes |
The path to a file containing newline separated IP prefixes (v4 or v6) which can be used for filtering events with various filters. | |
poll_interval |
go:DurationString |
5s | How often to check the file for changes. |
An example IPSet file is shown below:
Destination¶
The following parameters can be used to configure a destination:
| Parameter | Type | Default | Description |
|---|---|---|---|
blackhole |
boolean |
false | Messages to this destination will be dropped |
burst |
integer |
0 | When rate limiting, allow burst size of n events |
channel_buf_size |
integer |
100 | The size of the channel buffer used to send batches to destinations. If the destination is writing very large files, e.g. for s3 storage destinations, which can halt processing of new messages for that destination, it can help to increase the buffer size to avoid dropping batches. Use the dstore_dist_route_remote_drop_total metric as a guide - e.g. if it is regularly greater than 0 (increasing the number of workers can also help here). |
framing |
string |
16bit |
The framing type to use when sending protobuf to this destination. Possible values are 16bit, 32bit and repeated. This is ignored when the destination does not support protobuf, or when the output encoding is not protobuf. |
ip_obfuscation |
IP Obfuscation | Settings that control obfuscation of from/to IP addresses. | |
rate |
integer |
0 | Rate limit throughput to n messages per second (0 or empty means no rate limiting will take place). |
sample |
integer |
0 | Sample messages to one out of n messages. |
type |
string |
pdns |
Type of destination. Available options: "pdns" "kafka" "storage" "websub" "otel". See below for more configuration options specific to each destination type. |
Some notes on the framing parameter for destinations:
- The only destinations that support protobuf output are
pdns,kafkaandstorage - Only
pdnsandstoragedestinations support theframingparameter. - The
kafkadestination ignores theframingparameter, as it always usesrepeatedframing. - All other destinations do not support protobuf and thus ignore the framing parameter.
IP Obfuscation¶
| Parameter | Type | Default | Description |
|---|---|---|---|
enabled |
boolean |
false |
If true, obfuscate IP addresses in messages before sending to the destination. This can be useful for privacy reasons or to pseudo-anonymize data. |
key |
string |
Encryption key. Must be 16 bytes long for ipcrypt-deterministic and 32 bytes for ipcrypt-pfx. Mutually exclusive with key_file. |
|
key_file |
string |
Filename to read the key from. Mutually exclusive with key. |
|
mode |
string |
ipcrypt-deterministic |
Obfuscation mode. Supported values are ipcrypt-pfx and ipcrypt-deterministic. |
obfuscate_to |
boolean |
false |
Also obfuscate the to IP address if enabled. By default only the from address is obfuscated. |
IP obfuscation uses an algorithm based on IPCrypt. By default, only the from IP address is obfuscated.
Since encryption rather than hashing is used, the process is reversible; this allows for the data to be stored privately but
still be able to be analyzed by the operations team if necessary, e.g. to track abuse.
The IP obfuscation modes are explained in more detail below:
ipcrypt-deterministic: IPs are obfuscated into an IPv6 address. This is the default mode, and is very fast (approx 5% performance degradation over no encryption).ipcrypt-pfx: IPs are obfuscated into either IPv6 or IPv4 address, depending on the input address. This mode maintains network structure in encrypted IP addresses. Addresses from the same network produce encrypted addresses that share a common prefix, enabling privacy-preserving network analytics while preventing identification of specific networks or users. However, this mode is much slower thanipcrypt-deterministic, with a best-case 50% overall performance degradation for serialization (IPv4 from/to), with even worse performance for IPv6 addresses. Care should be taken when using pfx-mode.
N.B. IP Obfuscation is not supported for pdns destinations, nor is it supported when the output encoding is protobuf (i.e. kafka destinations without json_encode enabled, or storage destinations with protobuf encoding). For otel destinations, IP obfuscation applies to generated log records and does not modify the embedded OpenTelemetry trace payload.
Destination: pdns¶
Additional parameters are available on dstore-dist destinations with type: pdns (or no type). These should be attributes of the destination item itself. For example:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
addresses |
List of string |
yes |
List of addresses of downstream servers supporting the pdns protobuf protocol. Should be either IP:port or host:port |
|
connect_timeout |
go:DurationString |
"5s" |
How long to wait before timing out connection attempts | |
distribute |
string |
all |
Distribution algorithm when multiple addresses are configured. Available options: "all","roundrobin", "sharded", "ordered" |
|
shardreplicas |
integer |
100 |
How many buckets to use for the hash table for sharded distribution type |
|
tlsconfig |
TLS Config | {} |
TLS configuration options | |
use_tls |
boolean |
false |
If true, attempt to connect to the addresses using TLS |
|
write_timeout |
go:DurationString |
"5s" |
How long to wait before timing out write attempts |
An explanation of the distribution algorithms is as follows:
- all: All messages are sent to all addresses.
- roundrobin: Messages are sent to addresses in a round-robin fashion.
- sharded: Messages are sent to addresses in a sharded fashion. The query name is used as a key to determine which address to send the message to, using a consistent hashing algorithm.
- ordered: Messages are sent to addresses in an ordered fashion. The first address is used if it is available, otherwise the second address is used, and so on.
Destination: kafka¶
Additional parameters are available on destinations with type: kafka. These should be nested attributes inside a kafka: item of the destination item itself. For example:
destinations:
mydestination:
type: kafka
kafka:
addresses:
- kafka.endpoint.local:9092
topic: mytopic
The nested kafka: attribute takes the following parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
addresses |
List of string |
yes |
List of addresses of kafka endpoints. Should be either IP:port or host:port |
|
async |
boolean |
false |
If true, dstore-dist writes to Kafka never block and all responses from Kafka are ignored |
|
balancer |
string |
"roundrobin" |
Balancer used to distribute Kafka messages amongst partitions. Available options: "roundrobin" "leastbytes" "fnv-1a" "crc32" "murmur2" |
|
batch_size |
integer |
10000 |
Number of messages which will constitute a batch. dstore-dist will wait for new messages until either the batch size is reached, or the batch_timeout is exceeded |
|
batch_timeout |
go:DurationString |
1ms |
Timeout before an incomplete batch is written to Kafka | |
compression |
string |
"" |
Compression codec to use. Available options: "gzip" "snappy" "lz4" "zstd" No compression is performed when empty |
|
exclude_fields |
List of string (see Include/Exclude fields) |
Specifies which fields to exclude from the output. Only applies to JSON encoding. By default all fields are included. Mutually exclusive with include_fields |
||
include_fields |
List of string (see Include/Exclude fields) |
Specifies which fields to include in the output. Only applies to JSON encoding. By default all fields are included. Mutually exclusive with exclude_fields |
||
instance_name |
string |
If configured, a header will be added to each Kafka message with this value | ||
json_encode |
boolean |
false |
If true, JSON encode the data before sending to Kafka. Otherwise protobuf is sent (with repeated framing when single_msgs is false) |
|
max_attempts |
integer |
2 |
Number of times a message will be attempted to send to kafka | |
max_msg_size |
integer |
900000 |
Maximum size of a kafka message (in bytes). Cannot be lower than 65536. |
|
num_workers |
integer |
2 |
Number of concurrent workers that will process protobuf messages and send them to kafka | |
read_timeout |
go:DurationString |
10s |
Timeout for reads from Kafka | |
required_acks |
string |
"one" |
How many acks are required from kafka. Available options: "one" "all" "none" |
|
sasl |
SASLConfig | Optional SASL configuration | ||
single_msgs |
boolean |
false |
If true, each Kafka message will only contain a single protobuf message |
|
tlsconfig |
TLS Config | {} |
TLS configuration options | |
topic |
string |
yes |
Name of Kafka topic to send messages to | |
use_tls |
boolean |
false |
If true, attempt to connect to the addresses using TLS |
|
write_timeout |
go:DurationString |
10s |
Timeout for writes to Kafka |
SASL Config¶
The kafka nested sasl: attribute takes the following parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
type |
string |
yes |
The type of SASL authentication to use, one of plain, scram256 or scram512 |
|
username |
string |
yes |
The username to use for authentication | |
password |
string |
The password to use for authentication. Will be ignored if password_file is provided |
||
password_file |
string |
A filename to read the password from. The file must have 0400 permissions. Overrides password if that is also specified |
Include and Exclude Fields¶
The lists of fields that can be included or excluded from the output of the destination for JSON encodings, and for storage destinations using parquet encoding, can be configured using the include_fields and exclude_fields parameters.
The following fields are always present in the output of the destination:
| Field | Notes |
|---|---|
type |
|
time_sec |
Combined with time_usec for the Timestamp parquet column. |
time_usec |
Combined with time_sec for the Timestamp parquet column. |
response.query_time_sec |
Only output if type is response. Combined with response.query_time_usec for the ResponseTimestamp parquet column. |
response.query_time_usec |
Only output if type is response. Combined with response.query_time_sec for the ResponseTimestamp parquet column. |
The following field names are valid for inclusion/exclusion:
| Field | Notes |
|---|---|
message_id |
|
server_identity |
|
socket_family |
|
socket_protocol |
|
from |
|
from_port |
|
to |
|
to_port |
|
in_bytes |
|
id |
|
query.qname |
|
query.qtype |
|
query.qclass |
|
response.code |
Only output if type is response |
response.rrs |
Only output if type is response |
response.tags |
Only output if type is response |
response.applied_policy |
Only output if type is response |
response.applied_policy_type |
Only output if type is response |
response.applied_policy_trigger |
Only output if type is response |
response.applied_policy_hit |
Only output if type is response |
response.applied_policy_kind |
Only output if type is response |
response.validation_state |
Only output if type is response |
original_requestor_subnet |
|
requestor_id |
|
initial_request_id |
|
device_id |
|
device_name |
|
newly_observed_domain |
|
meta |
|
trace |
The trace field is valid for JSON output only. It is not included in storage parquet output. |
http_version |
|
worker_id |
|
packet_cache_hit |
|
outgoing_queries |
|
header_flags |
|
edns_version |
|
ede |
|
ede_text |
|
open_telemetry_trace_id |
Destination: storage¶
Additional parameters are available on destinations with type: storage. These should be nested attributes inside a storage: item of the destination item itself. For example:
destinations:
mydestination:
type: storage
storage:
type: s3
encoding: json
options:
endpoint_url: https://my.s3.endpoint.local
bucket: myBucket
region: myRegion
The nested storage: attribute takes the following parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
encoding |
string |
"protobuf" |
Encoding used for the files. Available options: "protobuf" "json" "bind" and "parquet" |
|
exclude_fields |
List of string (see Include/Exclude fields) |
Specifies which fields to exclude from JSON or parquet output. By default all fields are included. Mutually exclusive with include_fields |
||
file_extension |
string |
If provided, each file stored will have .<file_extension> appended, e.g. "json" will append ".json" to the file/object name |
||
flush_interval |
go:DurationString |
300s |
Time between consecutive flushes to storage (only if max_size is not reached before this interval) |
|
include_fields |
List of string (see Include/Exclude fields) |
Specifies which fields to include in JSON or parquet output. By default all fields are included. Mutually exclusive with exclude_fields |
||
max_size |
integer |
Maximum size in bytes of the file (before compression). Defaults to dstore-dist's toplevel configuration item batchBufferSize. If batchBufferSize is not set the value will be 1048576. Note for "parquet" encoding, the default is 100MB, as parquet files should be large for good performance. |
||
num_workers |
integer |
2 |
Number of concurrent workers that will process protobuf messages and attempt to store them | |
options |
Storage Options | yes |
Configuration of the storage backend | |
parse_rd |
boolean |
false |
If true, use the value of the RD flags set in the protobuf rather than assuming it's true. Only applies to "bind" encoding |
|
request_timeout |
go:DurationString |
5s | How long to wait before giving up on sending requests to storage | |
type |
string |
"s3" |
Type of storage backend. Available options: "s3" "azure" "fs" |
|
use_compression |
boolean |
false |
If true, compress files using gzip compression |
Encoding Options¶
There are currently four encoding options available:
protobuf- This is the default encoding. The protobuf is stored as a single binary blob.json- Each message is encoded as a JSON string, with each message on a separate line. Fields can be controlled withinclude_fieldsandexclude_fields.bind- Each message is encoded using the bind query log format, with each message on a separate line. Note that this encoding only includes a few fields from the protobuf.parquet- The messages are stored in the parquet format. The parquet format is a columnar format, suitable for ingestion or querying by columnar DBs such as Clickhouse. Fields can be controlled withinclude_fieldsandexclude_fields.
For JSON, Protobuf and Parquet encodings, the type field is an integer which can be one of the following values:
| Value of Type | Description |
|---|---|
| 1 | DNS Query |
| 2 | DNS Response (also includes query) |
| 3 | DNS Outgoing Query |
| 4 | DNS Outgoing Response (also includes outgoing query) |
The parquet format includes the following columns:
| Column | Parquet type | Presence | Description |
|---|---|---|---|
Type |
unsigned integer | Mandatory | The type of the message: 1 for QUERY, 2 for RESPONSE, 3 for OUTGOING_QUERY and 4 for INCOMING_RESPONSE. |
Timestamp |
timestamp (millisecond) | Mandatory | The timestamp of the query, in milliseconds since the Unix epoch (in UTC not localtime), in parquet timestamp format. |
MessageID |
byte array | Optional | The UUID of the query. |
ServerIdentity |
byte array | Optional | ID of the server emitting the protobuf message. |
SocketFamily |
unsigned integer | Optional | Socket family as encoded in the protobuf. |
SocketProtocol |
unsigned integer | Optional | Socket protocol as encoded in the protobuf. |
SourceIP |
byte array | Optional | The IP address of the client that made the query. |
SourcePort |
unsigned integer | Optional | The source port of the DNS query. |
DestinationIP |
byte array | Optional | The IP address of the server that responded to the query. |
DestinationPort |
unsigned integer | Optional | The destination port of the DNS query. |
InBytes |
unsigned integer | Optional | Size of the query or response on the wire. |
ID |
unsigned integer | Optional | The DNS query or response ID. |
QueryName |
byte array | Optional | The DNS name that is being queried. Note that this includes the trailing dot. |
QueryType |
string | Optional | The type of query, e.g. A, AAAA, MX, etc. |
QueryClass |
string | Optional | The query class, e.g. IN. |
Rcode |
unsigned integer | Optional | The response code for the query, e.g. 0 for NOERROR. This is only populated for response messages. |
ResponseRRs |
list of ResponseRR fields | Optional | Resource records from the response. |
Tags |
list of strings | Optional | Any tags present in the response. This is encoded as a parquet Array. |
ResponseTimestamp |
timestamp (millisecond) | Mandatory if type is response | The timestamp of the original query for a response message, in milliseconds since the Unix epoch (in UTC not localtime), in parquet timestamp format. |
ResponseAppliedPolicy |
byte array | Optional | Filtering policy applied to the response. |
ResponseAppliedPolicyType |
unsigned integer | Optional | Type of the filtering policy applied to the response. |
ResponseAppliedPolicyTrigger |
byte array | Optional | The RPZ trigger for the response policy. |
ResponseAppliedPolicyHit |
byte array | Optional | The value that caused the response policy hit. |
ResponseAppliedPolicyKind |
unsigned integer | Optional | Kind of response policy action applied. |
ResponseValidationState |
unsigned integer | Optional | DNSSEC validation state for the response. |
OriginalRequestorSubnet |
byte array | Optional | EDNS Client Subnet value. |
RequestorID |
byte array | Optional | The username of the client that made the query. |
InitialRequestID |
byte array | Optional | UUID of the incoming query that initiated this outgoing query or incoming response. |
DeviceID |
byte array | Optional | The device ID of the client that made the query. |
DeviceName |
byte array | Optional | The device name of the client that made the query. |
NewlyObservedDomain |
boolean | Optional | Whether the domain has not been seen before. |
Meta |
map to Meta fields | Optional | Arbitrary metadata, encoded as a parquet map from string keys to nested values. |
HTTPVersion |
unsigned integer | Optional | HTTP version used for DNS over HTTP. |
WorkerID |
unsigned integer | Optional | Worker thread ID. |
PacketCacheHit |
boolean | Optional | Whether the answer came from the packet cache. |
OutgoingQueries |
unsigned integer | Optional | Number of outgoing queries used to answer the query. |
HeaderFlags |
unsigned integer | Optional | DNS header flags in wire format. |
EdnsVersion |
unsigned integer | Optional | EDNS version and flags in wire format. |
Parquet ResponseRR Fields¶
Each item in ResponseRRs is encoded as a ResponseRR nested record with the following fields:
| Field | Parquet type | Description |
|---|---|---|
Name |
byte array | Resource record name. |
Type |
string | Resource record type, e.g. A, AAAA, CNAME. |
Class |
string | Resource record class, e.g. IN. |
TTL |
unsigned integer | Resource record TTL. |
Rdata |
byte array | Resource record data, hex encoded, e.g. 7f000001 would represent 127.0.0.1 |
UDR |
boolean | Whether this is the first time this record has been seen for the question. |
Parquet Meta Fields¶
Meta is encoded as a parquet map. Each map key is the metadata key string, and each map value is a nested record with the following fields:
| Field | Parquet type | Description |
|---|---|---|
StringVal |
list of byte arrays | String metadata values as raw protobuf bytes. |
IntVal |
list of integers | Integer metadata values. |
Storage Options¶
For storage with type: s3 the following can be configured under options:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
access_key |
string |
S3 access key. | ||
access_key_file |
string |
File containing the S3 access key. | ||
bucket |
string |
yes |
Name of the S3 bucket | |
client_timeout |
go:DurationString |
15m |
Specifies a time limit for requests made by this HTTP Client. The timeout includes connection time, any redirects, and reading the response body. | |
create_bucket |
boolean |
no |
Whether to try to create the bucket | |
dial_timeout |
go:DurationString |
10s |
The maximum amount of time a dial will wait for a connect to complete | |
dial_keep_alive |
go:DurationString |
10s |
Specifies the interval between keep-alive probes for an active network connection | |
endpoint_url |
string |
yes |
Endpoint of the S3 service to connect to | |
global_prefix |
string |
A prefix applied to all operations, allowing work within a prefix seamlessly | ||
idle_conn_timeout |
go:DurationString |
90s |
The maximum amount of time an idle (keep-alive) connection will remain idle before closing itself | |
init_timeout |
go:DurationString |
20s |
The time we allow for initialisation, like credential checking and bucket creation | |
max_idle_conns |
integer |
100 |
Controls the maximum number of idle (keep-alive) connections | |
num_minio_threads |
integer |
4 |
Controls the number of threads to be used in the multipart put object operations | |
region |
string |
"us-east-1" |
Region used when connecting to the S3 endpoint | |
secret_key |
string |
S3 secret key. | ||
secret_key_file |
string |
File containing the S3 secret key. | ||
secrets_refresh_interval |
go:DurationString |
15s |
Time between each secrets retrieval. | |
tls |
TLS Config | {} |
TLS configuration options | |
tls_handshake_timeout |
go:DurationString |
10s |
Specifies the maximum amount of time to wait for a TLS handshake |
For storage with type: azure the following can be configured under options:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
account_key |
string |
Azure Storage account key. Required with account_name when use_shared_key is enabled and account_key_file is not set. |
||
account_key_file |
string |
File containing the Azure Storage account key. Required with account_name when use_shared_key is enabled and account_key is not set. |
||
account_name |
string |
Azure Storage account name. Required unless endpoint_url is set. |
||
client_timeout |
go:DurationString |
15m |
Specifies a time limit for requests made by this HTTP Client. The timeout includes connection time, any redirects, and reading the response body. | |
concurrency |
integer |
1 |
Maximum number of concurrent upload workers used by Azure block blob stream uploads. | |
container |
string |
yes |
Name of the Azure Blob Storage container. | |
create_container |
boolean |
no |
Whether to try to create the container. | |
dial_keep_alive |
go:DurationString |
10s |
Specifies the interval between keep-alive probes for an active network connection. | |
dial_timeout |
go:DurationString |
10s |
The maximum amount of time a dial will wait for a connect to complete. | |
endpoint_url |
string |
Endpoint of the Azure Blob Storage service to connect to. This can be used for Azurite or custom endpoints. | ||
global_prefix |
string |
A prefix applied to all operations, allowing work within a prefix seamlessly. | ||
idle_conn_timeout |
go:DurationString |
90s |
The maximum amount of time an idle (keep-alive) connection will remain idle before closing itself. | |
init_timeout |
go:DurationString |
20s |
The time we allow for initialisation, like credential checking and container creation. | |
max_idle_conns |
integer |
100 |
Controls the maximum number of idle (keep-alive) connections. | |
secrets_refresh_interval |
go:DurationString |
15s |
Time between each secrets retrieval when account_key_file is used. |
|
tls |
TLS Config | {} |
TLS configuration options. | |
tls_handshake_timeout |
go:DurationString |
10s |
Specifies the maximum amount of time to wait for a TLS handshake. | |
update_marker_force_list_interval |
go:DurationString |
5m |
When use_update_marker is enabled, force a full LIST after this interval even if the update marker has not changed. |
|
use_shared_key |
boolean |
no |
Whether to authenticate with an account key. When disabled, Azure default credentials are used. | |
use_update_marker |
boolean |
no |
Whether to write and read an update marker object to reduce Azure LIST calls. If enabled, it must be enabled on all instances using this container and prefix. |
For storage with type: fs the following can be configured under options:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
root_path |
string |
yes |
The path to a directory in which the files will be stored |
Destination: websub¶
Additional parameters are available on destinations with type: websub. These should be nested attributes inside a websub: item of the destination item itself. For example:
destinations:
mydestination:
type: websub
websub:
client_id: dstoreuser
client_secret: 12345
token_url: https://myidp.example.com/token
scopes:
- foo
- bar
publish_url: https://websub.example.com/
tlsconfig:
insecure_skip_verify: true
topic: dnsmessage
request_timeout: 1s
headers:
X-Custom-Header: foobar
The nested websub: attribute takes the following parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
client_id |
string |
yes |
The Client ID to use for authenticating to the token endpoint | |
client_secret |
string |
yes |
The Client Secret to use for authenticating to the token endpoint | |
exclude_fields |
List of string (see Include/Exclude fields) |
Specifies which fields to exclude from the output. By default all fields are included. Mutually exclusive with include_fields |
||
headers |
map |
Map of headers, with the header name followed by the value | ||
include_fields |
List of string (see Include/Exclude fields) |
Specifies which fields to include in the output. By default all fields are included. Mutually exclusive with exclude_fields |
||
max_size |
integer |
1048576 |
Max size in bytes of the messages field in the JSON sent to the websub server | |
num_workers |
integer |
2 |
Number of concurrent workers to use - add more if performance is an issue | |
publish_url |
string |
yes |
The URL of the websub endpoint. If the URL path does not end with /webSub/v1/publish then that path will be appended to the URL |
|
request_timeout |
go:DurationString |
10s |
The request timeout when sending to the websub endpoint | |
scopes |
array of string |
If specified, which scopes to request from the token endpoint | ||
tlsconfig |
TLS Config | Optional TLS configuration for the connections to the websub and token endpoints | ||
token_url |
string |
yes |
The URL of the token endpoint | |
topic |
string |
yes |
The topic to use when sending to the websub endpoint |
See dstore-dist manpage for details of the JSON that is sent in the body of the POST request to the WebSub endpoint.
Destination: otel¶
Additional parameters are available on destinations with type: otel. These should be nested attributes inside a otel: item of the destination item itself. For example:
destinations:
otel-traces:
type: otel
otel:
target: host.example.com:4317
tlsconfig:
insecure_skip_verify: true
request_timeout: 1s
otel-logs:
type: otel
ip_obfuscation:
enabled: true
key_file: /etc/dstore-dist/ipcrypt.key
otel:
target: collector.example.com:4317
disable_traces: true
enable_logs: true
log_include_fields:
- query.qname
- query.qtype
- response.tags
- response.code
- from
By default, an otel destination sends OpenTelemetry traces from the openTelemetryData field. Trace forwarding should only receive messages which contain OpenTelemetry data; otherwise the destination has no trace payload to send. Use the has_otel_data filter for trace-only routes:
Set enable_logs: true to convert each DNS message into an OTLP log record. If both traces and logs are enabled on the same destination, dstore-dist exports both signals to the configured collector. Use disable_traces: true for a logs-only destination.
The nested otel: attribute takes the following parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
disable_traces |
boolean |
false |
If true, do not export embedded OpenTelemetry trace data from messages. | |
enable_logs |
boolean |
false |
If true, convert DNS messages into OTLP log records and export them to the logs service. | |
log_exclude_fields |
List of string (see Include/Exclude fields) |
Specifies which DNS fields to exclude from generated OTel log attributes. Mutually exclusive with log_include_fields. |
||
log_include_fields |
List of string (see Include/Exclude fields) |
Specifies which DNS fields to include in generated OTel log attributes. By default all fields are included. Mutually exclusive with log_exclude_fields. |
||
max_size |
integer |
1048576 |
Maximum size in bytes sent to the target in a single gRPC request. | |
num_workers |
integer |
4 |
Number of concurrent workers to use - add more if performance is an issue. | |
request_timeout |
go:DurationString |
5s |
Request timeout for exports via OTLP. | |
target |
string |
yes |
The OTLP endpoint to send data to using gRPC. You can use the dns:// URI scheme as well. | |
tlsconfig |
TLS Config | Optional TLS configuration for the connection to the target. |
OTel log attributes¶
Generated OTel logs use the log record event name dns.query, dns.response, dns.outgoing_query, dns.incoming_response, according to the DNS message type. Log records have severity INFO and a short string body such as DNS response.
The attributes emitted for generated OTel logs depend on the DNS message contents and on log_include_fields / log_exclude_fields. The following table lists the possible attributes. Unless noted otherwise, attributes are log record attributes.
| Attribute name | Type | Description |
|---|---|---|
service.name |
string |
Resource attribute. Always set to powerdns. |
service.instance.id |
string |
Resource attribute. Server identity from the DNS message, when present. |
dns.id |
int |
DNS message identifier. |
dns.question.name |
string |
Query name. |
dns.question.type |
string |
Query type name, such as A or AAAA; numeric string for unknown types. |
dns.question.class |
string |
Query class name, such as IN; numeric string for unknown classes. |
dns.message.id |
bytes |
Binary message ID. |
dns.message.size |
int |
Input message size in bytes. |
network.type |
string |
Network address family: ipv4 or ipv6. |
network.transport |
string |
Transport protocol, such as udp or tcp. |
dns.transport |
string |
DNS transport name, such as udp, tcp, dot, doh, dnscrypt_udp, or dnscrypt_tcp. |
network.protocol.name |
string |
Application protocol name. Set to http for DNS over HTTPS messages. |
network.protocol.version |
string |
HTTP protocol version for DNS over HTTPS messages, when known. |
client.address |
string |
Client IP address. If IP obfuscation is enabled on the destination, this contains the obfuscated source address. |
client.port |
int |
Client source port. |
server.address |
string |
Server IP address. If IP obfuscation is enabled on the destination, this contains the obfuscated destination address. |
server.port |
int |
Server destination port. |
dns.response.rcode |
int |
DNS response code. |
dns.response.rrs |
array<DNS Response RR]> |
Response resource records. |
dns.response.tags |
array<string> |
Response tags. |
dns.policy.name |
string |
Applied policy name. |
dns.policy.type |
string |
Applied policy type. |
dns.policy.trigger |
string |
Applied policy trigger. |
dns.policy.hit |
string |
Applied policy hit. |
dns.policy.kind |
string |
Applied policy kind. |
dns.dnssec.validation_state |
string |
DNSSEC validation state. |
dns.response.time_unix_nano |
int |
Response timestamp in Unix nanoseconds. This is emitted when the DNS message includes a response timestamp. |
dns.edns.client_subnet |
string |
EDNS Client Subnet address, when present. |
enduser.id |
string |
Requestor ID. |
dns.initial_request.id |
bytes |
Binary initial request ID. |
enduser.device.id |
string |
Device ID. |
enduser.device.name |
string |
Device name. |
dns.question.newly_observed |
bool |
Whether the queried domain is newly observed. |
thread.id |
int |
Worker ID. |
dns.cache.hit |
bool |
Whether the packet cache was hit. |
dns.outgoing_queries.count |
int |
Number of outgoing queries. |
dns.header.flags |
int |
DNS header flags. |
dns.edns.version |
int |
EDNS version. |
dns.ede |
int |
Extended DNS Error code. |
dns.ede.text |
string |
Extended DNS Error text. |
DNS Response RR¶
| Attribute name | Type | Description |
|---|---|---|
name |
string |
Name of the RR, e.g. powerdns.com. |
ttl |
int |
TTL of the RR, e.g. 3600 |
class |
string |
Class of the RR, e.g. IN |
type |
string |
Type of the RR, e.g. AAAA |
rdata |
string |
Record data, e.g. 1.2.3.4 |
Route¶
Parameters which can be used to configure a dstore-dist route:
destinations:
mydestination:
type: pdns
addresses:
- another.dstoredist.endpoint.local:1234
routes:
myroute:
destinations:
- mydestination
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
append_tags |
List of string |
[] |
List of tags which will be appended to each message for this route | |
destinations |
List of string |
yes |
List of names of destinations, these must have been configured on this dstore-dist instance | |
filters |
List of Filter | {} |
Filters to restrict which messages are sent for this route |
Filters¶
By default, all events will be sent to a particular destination, however configuring filters for a route allows only events matching the filter to be sent.
For example the following filters configuration ensures that only events that contain the query name foo.com
and are sent over IPv4 transport are sent to the destinations listed under myroute:
destinations:
mydestination:
type: pdns
addresses:
- another.dstoredist.endpoint.local:1234
routes:
myroute:
destinations:
- mydestination
filters:
- qname: foo.com
- is_ipv4: true
Note that the top-level filters are joined with an implicit and filter, meaning that all filters have to match for a message to reach the specified destination(s).
Matching Filters¶
Matching filters are used to match events based on specific information in the query/response. The list of possible filters is listed below:
| Parameter | Type | Default | Description |
|---|---|---|---|
dst_port |
integer |
Matches the destination (to) port in the message | |
dst_port_gtedst_port_gtdst_port_ltedst_port_lt |
integer |
These perform integer comparisons on the dst_port field in the message |
|
dst_port_not |
integer |
This is simply the inverse of dst_port |
|
edns_version |
integer |
Match the edns version in the message | |
edns_version_gteedns_version_gtedns_version_lteedns_version_lt |
integer |
These perform integer comparisons on the edns version in the message | |
edns_version_not |
integer |
This is simply the inverse of edns_version | |
from_in_ipset |
string |
Match all messages where the from IP is in a range contained in the named IP set | |
has_deviceid |
boolean |
Matches if the message has a deviceid field | |
has_policy |
boolean |
Matches if message has an appliedPolicy field in the response | |
has_requestorid |
boolean |
Matches if message has a requestorID fields in the response | |
has_tags |
boolean |
Matches if message has any tags set | |
has_aa_flag |
boolean |
Matches if message has AA flag set | |
has_tc_flag |
boolean |
Matches if message has TC flag set | |
has_rd_flag |
boolean |
Matches if message has RD flag set | |
has_ra_flag |
boolean |
Matches if message has RA flag set | |
has_ad_flag |
boolean |
Matches if message has AD flag set | |
has_cd_flag |
boolean |
Matches if message has CD flag set | |
has_do_flag |
boolean |
Matches if message has DO flag set | |
has_otel_data |
boolean |
Matches if message has an non-empty OpenTelemetryData field | |
has_policy |
boolean |
Matches if message has an appliedPolicy field in the response | |
has_unique_domain_response |
boolean |
Matches if message has a unique domain response flag set in any response RR. Only applied to responses. | |
is_ipv4 |
boolean |
Matches if the DNS query was received over IPv4 | |
is_ipv4 |
boolean |
Matches if the DNS query was received over IPv4 | |
is_response |
boolean |
Matches if the message is a response message (as opposed to a query message) | |
is_query |
boolean |
Matches if the message is a query message (as opposed to a response message) | |
is_outgoing_query |
boolean |
Matches if the message is an outgoing query message (i.e. a query sent by a server) | |
is_incoming_response |
boolean |
Matches if the message is an incoming response message (i.e. in response to an outgoing query) | |
is_tcp |
boolean |
Matches if the DNS query was received over TCP | |
is_udp |
boolean |
Matches if the DNS query was received over UDP | |
is_newly_observed_domain |
boolean |
Matches if the DNS query was a newly observed domain | |
is_cache_hit |
boolean |
Matches if the DNS query was answered without performing outgoing queries | |
is_packet_cache_hit |
boolean |
Matches if the DNS query was answered specifically from the packet cache | |
latency_msec |
integer |
Matches the latency field in the message, in milliseconds | |
latency_msec_gtelatency_msec_gtlatency_msec_ltelatency_msec_lt |
integer |
These perform integer comparisons on the latency_msec field in the message |
|
latency_msec_not |
integer |
This is simply the inverse of latency_msec |
|
meta_key |
string |
Matches if there is a meta field key with this name | |
meta_key_int |
string |
Matches meta field key and value, in the form key= |
|
meta_key_string |
string |
Matches meta field key and value, in the form key= |
|
outgoing_queries |
integer |
Matches the number of outgoing queries this event generated | |
outgoing_queries_gteoutgoing_queries_gtoutgoing_queries_lteoutgoing_queries_lt |
integer |
These perform integer comparisons on the outgoing_queries field in the message |
|
outgoing_queries_not |
integer |
This is simply the inverse of outgoing_queries |
|
policy_kind |
string |
Matches if the policyKind field is a match (case-insensitive). Possible values for policy_kind are none, noaction, drop, nxdomain, nodata, truncate. |
|
policy_type |
string |
Matches if the policyType field is a match (case-insensitive). Possible values for policy_type are none, unknown, qname, clientip, responseip, nsdname, nsip. |
|
qname |
string |
The value is a domain name; the filter matches if the query qname is an exact match (case-insensitive) for the specified domain name. | |
qname_sub |
string |
The value is a domain name; the filter matches if the query qname is a subdomain of the specified domain name. Matches are case-insensitive. | |
qtype |
string or integer |
The value matches the query resource record type of the request. It can be specified as a string or an integer, as any string will be converted to an integer using the mapping specified in https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml. If the type is very new, you may need to use the integer version. | |
qtype_gteqtype_gtqtype_lteqtype_lt |
string or integer |
These perform integer comparisons on qtype, after converting the type to an integer | |
qtype_not |
string or integer |
This is simply the inverse of qtype | |
requestor_id |
string |
Match if the requestor_id field is a match | |
reqsubnet_in_ipset |
string |
Match all messages where the 'origRequestedSubnet' IP is in a range contained in the named IP set | |
rcode |
integer |
Match the response code in the message (only for messages that contain a response) | |
rcode_gtercode_gtrcode_ltercode_lt |
integer |
These perform integer comparisons on the response code in the message | |
rcode_not |
integer |
This is simply the inverse of rcode | |
src_port |
integer |
Matches the source (from) port in the message | |
src_port_gtesrc_port_gtsrc_port_ltesrc_port_lt |
integer |
These perform integer comparisons on the src_port field in the message |
|
src_port_not |
integer |
This is simply the inverse of src_port |
|
tag |
string |
Match a specific tag | |
tag_prefix |
string |
Match the start of a tag |
Boolean Logic Filters¶
The and, or and not filters are used to combine or invert matching filters to create more complex filter patterns.
| Parameter | Type | Default | Description |
|---|---|---|---|
and |
List of Filter | Applies a logical AND to all the specified filters | |
not |
Filter | Inverts the specified filter | |
or |
List of Filter | Applies a logical OR to all the specified filters |
For example: