Built-in webserver

To visually interact with dnsdist, try add webserver() to the configuration:

webserver("127.0.0.1:8083", "supersecretpassword", "supersecretAPIkey")

Now point your browser at http://127.0.0.1:8083 and log in with any username, and that password. Enjoy!

Security of the Webserver

The built-in webserver serves its content from inside the binary, this means it will not and connot read from disk.

By default, our web server sends some security-related headers:

X-Content-Type-Options: nosniff
X-Frame-Options: deny
X-Permitted-Cross-Domain-Policies: none
X-XSS-Protection: 1; mode=block
Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'

You can override those headers, or add custom headers by using the last parameter to webserver(). For example, to remove the X-Frame-Options header and add a X-Custom one:

webserver("127.0.0.1:8080", "supersecret", "apikey", {["X-Frame-Options"]= "", ["X-Custom"]="custom"}

Credentials can be changed over time using the setWebserverConfig() function.

dnsdist API

To access the API, the apikey must be set in the webserver() function. Use the API, this key will need to be sent to dnsdist in the X-API-Key request header. An HTTP 401 response is returned when a wrong or no API key is received. A 404 response is generated is the requested endpoint does not exist. And a 405 response is returned when the HTTP methos is not allowed.

URL Endpoints

GET /jsonstat

Get statistics from dnsdist in JSON format. The Accept request header is ignored. This endpoint accepts a command query for different statistics:

  • stats: Get all Statistics as a JSON dict
  • dynblocklist: Get all current dynamic blocks, keyed by netmask
  • ebpfblocklist: Idem, but for eBPF blocks

Example request:

GET /jsonstat?command=stats HTTP/1.1
Host: example.com
Accept: application/json, text/javascript
Example response:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Connection: close
Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
Content-Type: application/json
X-Content-Type-Options: nosniff
X-Frame-Options: deny
X-Permitted-Cross-Domain-Policies: none
X-Xss-Protection: 1; mode=block

{"acl-drops": 0, "block-filter": 0, "cache-hits": 0, "cache-misses": 0, "cpu-sys-msec": 633, "cpu-user-msec": 499, "downstream-send-errors": 0, "downstream-timeouts": 0, "dyn-block-nmg-size": 1, "dyn-blocked": 3, "empty-queries": 0, "fd-usage": 17, "latency-avg100": 7651.3982737482893, "latency-avg1000": 860.05142763680249, "latency-avg10000": 87.032142373878372, "latency-avg1000000": 0.87146026426551759, "latency-slow": 0, "latency0-1": 0, "latency1-10": 0, "latency10-50": 22, "latency100-1000": 1, "latency50-100": 0, "no-policy": 0, "noncompliant-queries": 0, "noncompliant-responses": 0, "over-capacity-drops": 0, "packetcache-hits": 0, "packetcache-misses": 0, "queries": 26, "rdqueries": 26, "real-memory-usage": 6078464, "responses": 23, "rule-drop": 0, "rule-nxdomain": 0, "rule-refused": 0, "self-answered": 0, "server-policy": "leastOutstanding", "servfail-responses": 0, "too-old-drops": 0, "trunc-failures": 0, "uptime": 412}

Example request:

GET /jsonstat?command=dynblocklist HTTP/1.1
Host: example.com
Accept: application/json, text/javascript
Example response:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Connection: close
Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
Content-Type: application/json
X-Content-Type-Options: nosniff
X-Frame-Options: deny
X-Permitted-Cross-Domain-Policies: none
X-Xss-Protection: 1; mode=block

{"127.0.0.1/32": {"blocks": 3, "reason": "Exceeded query rate", "seconds": 10}}
Query Parameters:
 
  • command – one of stats, dynblocklist or ebpfblocklist
GET /metrics

Get statistics from dnsdist in Prometheus format.

Example request:

GET /metrics HTTP/1.1
Example response:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
Content-Type: text/plain
X-Content-Type-Options: nosniff
X-Frame-Options: deny
X-Permitted-Cross-Domain-Policies: none
X-Xss-Protection: 1; mode=block

# HELP dnsdist_responses Number of responses received from backends
# TYPE dnsdist_responses counter
dnsdist_responses 0
# HELP dnsdist_servfail_responses Number of SERVFAIL answers received from backends
# TYPE dnsdist_servfail_responses counter
dnsdist_servfail_responses 0
# HELP dnsdist_queries Number of received queries
# TYPE dnsdist_queries counter
dnsdist_queries 0
# HELP dnsdist_acl_drops Number of packets dropped because of the ACL
# TYPE dnsdist_acl_drops counter
dnsdist_acl_drops 0
# HELP dnsdist_rule_drop Number of queries dropped because of a rule
# TYPE dnsdist_rule_drop counter
dnsdist_rule_drop 0
# HELP dnsdist_rule_nxdomain Number of NXDomain answers returned because of a rule
# TYPE dnsdist_rule_nxdomain counter
dnsdist_rule_nxdomain 0
# HELP dnsdist_rule_refused Number of Refused answers returned because of a rule
# TYPE dnsdist_rule_refused counter
dnsdist_rule_refused 0
# HELP dnsdist_rule_servfail Number of SERVFAIL answers received because of a rule
# TYPE dnsdist_rule_servfail counter
dnsdist_rule_servfail 0
# HELP dnsdist_self_answered Number of self-answered responses
# TYPE dnsdist_self_answered counter
dnsdist_self_answered 0
# HELP dnsdist_downstream_timeouts Number of queries not answered in time by a backend
# TYPE dnsdist_downstream_timeouts counter
dnsdist_downstream_timeouts 0
# HELP dnsdist_downstream_send_errors Number of errors when sending a query to a backend
# TYPE dnsdist_downstream_send_errors counter
dnsdist_downstream_send_errors 0
# HELP dnsdist_trunc_failures Number of errors encountered while truncating an answer
# TYPE dnsdist_trunc_failures counter
dnsdist_trunc_failures 0
# HELP dnsdist_no_policy Number of queries dropped because no server was available
# TYPE dnsdist_no_policy counter
dnsdist_no_policy 0
# HELP dnsdist_latency0_1 Number of queries answered in less than 1ms
# TYPE dnsdist_latency0_1 counter
dnsdist_latency0_1 0
# HELP dnsdist_latency1_10 Number of queries answered in 1-10 ms
# TYPE dnsdist_latency1_10 counter
dnsdist_latency1_10 0
# HELP dnsdist_latency10_50 Number of queries answered in 10-50 ms
# TYPE dnsdist_latency10_50 counter
dnsdist_latency10_50 0
# HELP dnsdist_latency50_100 Number of queries answered in 50-100 ms
# TYPE dnsdist_latency50_100 counter
dnsdist_latency50_100 0
# HELP dnsdist_latency100_1000 Number of queries answered in 100-1000 ms
# TYPE dnsdist_latency100_1000 counter
dnsdist_latency100_1000 0
# HELP dnsdist_latency_slow Number of queries answered in more than 1 second
# TYPE dnsdist_latency_slow counter
dnsdist_latency_slow 0
# HELP dnsdist_latency_avg100 Average response latency in microseconds of the last 100 packets
# TYPE dnsdist_latency_avg100 gauge
dnsdist_latency_avg100 0
# HELP dnsdist_latency_avg1000 Average response latency in microseconds of the last 1000 packets
# TYPE dnsdist_latency_avg1000 gauge
dnsdist_latency_avg1000 0
# HELP dnsdist_latency_avg10000 Average response latency in microseconds of the last 10000 packets
# TYPE dnsdist_latency_avg10000 gauge
dnsdist_latency_avg10000 0
# HELP dnsdist_latency_avg1000000 Average response latency in microseconds of the last 1000000 packets
# TYPE dnsdist_latency_avg1000000 gauge
dnsdist_latency_avg1000000 0
# HELP dnsdist_uptime Uptime of the dnsdist process in seconds
# TYPE dnsdist_uptime gauge
dnsdist_uptime 39
# HELP dnsdist_real_memory_usage Current memory usage in bytes
# TYPE dnsdist_real_memory_usage gauge
dnsdist_real_memory_usage 10276864
# HELP dnsdist_noncompliant_queries Number of queries dropped as non-compliant
# TYPE dnsdist_noncompliant_queries counter
dnsdist_noncompliant_queries 0
# HELP dnsdist_noncompliant_responses Number of answers from a backend dropped as non-compliant
# TYPE dnsdist_noncompliant_responses counter
dnsdist_noncompliant_responses 0
# HELP dnsdist_rdqueries Number of received queries with the recursion desired bit set
# TYPE dnsdist_rdqueries counter
dnsdist_rdqueries 0
# HELP dnsdist_empty_queries Number of empty queries received from clients
# TYPE dnsdist_empty_queries counter
dnsdist_empty_queries 0
# HELP dnsdist_cache_hits Number of times an answer was retrieved from cache
# TYPE dnsdist_cache_hits counter
dnsdist_cache_hits 0
# HELP dnsdist_cache_misses Number of times an answer not found in the cache
# TYPE dnsdist_cache_misses counter
dnsdist_cache_misses 0
# HELP dnsdist_cpu_user_msec Milliseconds spent by dnsdist in the user state
# TYPE dnsdist_cpu_user_msec counter
dnsdist_cpu_user_msec 28
# HELP dnsdist_cpu_sys_msec Milliseconds spent by dnsdist in the system state
# TYPE dnsdist_cpu_sys_msec counter
dnsdist_cpu_sys_msec 32
# HELP dnsdist_fd_usage Number of currently used file descriptors
# TYPE dnsdist_fd_usage gauge
dnsdist_fd_usage 17
# HELP dnsdist_dyn_blocked Number of queries dropped because of a dynamic block
# TYPE dnsdist_dyn_blocked counter
dnsdist_dyn_blocked 0
# HELP dnsdist_dyn_block_nmg_size Number of dynamic blocks entries
# TYPE dnsdist_dyn_block_nmg_size gauge
dnsdist_dyn_block_nmg_size 0
dnsdist_server_queries{server="1_1_1_1",address="1.1.1.1:53"} 0
dnsdist_server_drops{server="1_1_1_1",address="1.1.1.1:53"} 0
dnsdist_server_latency{server="1_1_1_1",address="1.1.1.1:53"} 0
dnsdist_server_senderrors{server="1_1_1_1",address="1.1.1.1:53"} 0
dnsdist_server_outstanding{server="1_1_1_1",address="1.1.1.1:53"} 0
dnsdist_server_order{server="1_1_1_1",address="1.1.1.1:53"} 1
dnsdist_server_weight{server="1_1_1_1",address="1.1.1.1:53"} 1
dnsdist_server_queries{server="1_0_0_1",address="1.0.0.1:53"} 0
dnsdist_server_drops{server="1_0_0_1",address="1.0.0.1:53"} 0
dnsdist_server_latency{server="1_0_0_1",address="1.0.0.1:53"} 0
dnsdist_server_senderrors{server="1_0_0_1",address="1.0.0.1:53"} 0
dnsdist_server_outstanding{server="1_0_0_1",address="1.0.0.1:53"} 0
dnsdist_server_order{server="1_0_0_1",address="1.0.0.1:53"} 1
dnsdist_server_weight{server="1_0_0_1",address="1.0.0.1:53"} 2
dnsdist_frontend_queries{frontend="127.0.0.1:1153",proto="udp"} 0
dnsdist_frontend_queries{frontend="127.0.0.1:1153",proto="tcp"} 0
dnsdist_pool_servers{pool="_default_"} 2
dnsdist_pool_cache_size{pool="_default_"} 200000
dnsdist_pool_cache_entries{pool="_default_"} 0
dnsdist_pool_cache_hits{pool="_default_"} 0
dnsdist_pool_cache_misses{pool="_default_"} 0
dnsdist_pool_cache_deferred_inserts{pool="_default_"} 0
dnsdist_pool_cache_deferred_lookups{pool="_default_"} 0
dnsdist_pool_cache_lookup_collisions{pool="_default_"} 0
dnsdist_pool_cache_insert_collisions{pool="_default_"} 0
dnsdist_pool_cache_ttl_too_shorts{pool="_default_"} 0

Example prometheus configuration:

This is just the scrape job description, for details see the prometheus documentation.

job_name: dnsdist
scrape_interval: 10s
scrape_timeout: 2s
metrics_path: /metrics
basic_auth:
  username: dontcare
  password: yoursecret
GET /api/v1/servers/localhost

Get a quick overview of several parameters.

Response JSON Object:
 
  • acl (string) – A string of comma-separated netmasks currently allowed by the ACL.
  • cache-hit-response-rules (list) – A list of ResponseRule objects applied on cache hits
  • self-answered-response-rules (list) – A list of ResponseRule objects applied on self-answered queries
  • daemon_type (string) – The type of daemon, always “dnsdist”
  • frontends (list) – A list of Frontend objects
  • pools (list) – A list of Pool objects
  • response-rules (list) – A list of ResponseRule objects
  • rules (list) – A list of Rule objects
  • servers (list) – A list of Server objects
  • version (string) – The running version of dnsdist
GET /api/v1/servers/localhost/statistics

Returns a list of all statistics as StatisticItem.

GET /api/v1/servers/localhost/config

Returns a list of ConfigSetting objects.

GET /api/v1/servers/localhost/config/allow-from

Gets you the allow-from ConfigSetting, who’s value is a list of strings of all the netmasks in the ACL.

Example request:

GET /api/v1/servers/localhost/config/allow-from HTTP/1.1
X-API-Key: supersecretAPIkey
Example response:
HTTP/1.1 200 OK
Connection: close
Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
Content-Type: application/json
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-Frame-Options: deny
X-Permitted-Cross-Domain-Policies: none
X-Xss-Protection: 1; mode=block

{
    "name": "allow-from",
    "type": "ConfigSetting",
    "value": [
        "fc00::/7",
        "169.254.0.0/16",
        "100.64.0.0/10",
        "fe80::/10",
        "10.0.0.0/8",
        "127.0.0.0/8",
        "::1/128",
        "172.16.0.0/12",
        "192.168.0.0/16"
    ]
}
PUT /api/v1/servers/localhost/config/allow-from

Allows you to update the allow-from ACL with a list of netmasks.

Make sure you made the API writable using setAPIWritable().

Example request:

PUT /api/v1/servers/localhost/config/allow-from HTTP/1.1
Content-Length: 37
Content-Type: application/json
X-API-Key: supersecretAPIkey

{
    "value": [
        "127.0.0.0/8",
        "::1/128"
    ]
}
Example response:
HTTP/1.1 200 OK
Connection: close
Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
Content-Type: application/json
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-Frame-Options: deny
X-Permitted-Cross-Domain-Policies: none
X-Xss-Protection: 1; mode=block

{
    "name": "allow-from",
    "type": "ConfigSetting",
    "value": [
        "127.0.0.0/8",
        "::1/128"
    ]
}

JSON Objects

ConfigSetting

An object representing a global configuration element. The following configuration are returned:

Object Properties:
 
  • name (string) – The name of the setting
  • type (string) – “ConfigSetting”
  • value (string) – The value for this setting
Frontend

A description of a bind dnsdist is listening on.

Object Properties:
 
  • address (string) – IP and port that is listened on
  • id (integer) – Internal identifier
  • queries (integer) – The number of received queries on this bind
  • udp (boolean) – true if this is a UDP bind
  • tcp (boolean) – true if this is a TCP bind
Pool

A description of a pool of backend servers.

Object Properties:
 
  • id (integer) – Internal identifier
  • cacheDeferredInserts (integer) – The number of times an entry could not be inserted in the associated cache, if any, because of a lock
  • cacheDeferredLookups (integer) – The number of times an entry could not be looked up from the associated cache, if any, because of a lock
  • cacheEntries (integer) – The current number of entries in the associated cache, if any
  • cacheHits (integer) – The number of cache hits for the associated cache, if any
  • cacheLookupCollisions (integer) – The number of times an entry retrieved from the cache based on the query hash did not match the actual query
  • cacheInsertCollisions (integer) – The number of times an entry could not be inserted into the cache because a different entry with the same hash already existed
  • cacheMisses (integer) – The number of cache misses for the associated cache, if any
  • cacheSize (integer) – The maximum number of entries in the associated cache, if any
  • cacheTTLTooShorts (integer) – The number of times an entry could not be inserted into the cache because its TTL was set below the minimum threshold
  • name (string) – Name of the pool
  • serversCount (integer) – Number of backends in this pool
Rule

This represents a policy that is applied to queries

Object Properties:
 
  • action (string) – The action taken when the rule matches (e.g. “to pool abuse”)
  • action-stats (dict) – A list of statistics whose content varies depending on the kind of rule
  • id (integer) – The position of this rule
  • matches (integer) – How many times this rule was hit
  • rule (string) – The matchers for the packet (e.g. “qname==bad-domain1.example., bad-domain2.example.”)
  • uuid (string) – The UUID of this rule
ResponseRule

This represents a policy that is applied to responses

Object Properties:
 
  • action (string) – The action taken when the rule matches (e.g. “drop”)
  • id (integer) – The identifier (or order) of this rule
  • matches (integer) – How many times this rule was hit
  • rule (string) – The matchers for the packet (e.g. “qname==bad-domain1.example., bad-domain2.example.”)
Server

This object represents a backend server.

Changed in version 1.3.1: The dropRate property was added

Object Properties:
 
  • address (string) – The remote IP and port
  • id (integer) – Internal identifier
  • latency (integer) – The current latency of this backend server
  • name (string) – The name of this server
  • order (integer) – Order number
  • outstanding (integer) – Number of currently outstanding queries
  • pools ([string]) – The pools this server belongs to
  • qps (integer) – The current number of queries per second to this server
  • qpsLimit (integer) – The configured maximum number of queries per second
  • queries (integer) – Total number of queries sent to this backend
  • reuseds (integer) – Number of queries for which a response was not received in time
  • sendErrors (integer) – Number of network errors while sending a query to this server
  • state (string) – The state of the server (e.g. “DOWN” or “up”)
  • weight (integer) – The weight assigned to this server
  • dropRate (float) – The amount of packets dropped per second by this server
StatisticItem

This represents a statistics element.

Object Properties:
 
  • name (string) – The name of this statistic. See Statistics
  • type (string) – “StatisticItem”
  • value (integer) – The value for this item