あどけない話

Internet technologies

Status report of dnsext

This article reports the current status of the dnsext packages in Haskell. If you don't know what dnsext is, please read "Developing network related libraries in Haskell in 2022FY" first. The purpose of this project is provide DNS full resolver (cache server).

bowline

Our DNS full resolver is now called bowline named after the king of knots. (I used to climb rocks with double eight knot but I like bowline.) Most importantly, our DNSSEC verifier has been integrated into bowline by Kei Hibino.

New features

To make bowline practical, the following features have been added:

  • Configuration: bowline.conf is in the key-value format. Especially, local-zone:, local-data:, root-hints: and trust-anchor-file: can be specified.
  • Logging: the standard way of logging for DNS servers is DNSTAP whose format is protocol buffer and transport is fast stream. Instead of using other libraries, we implement them in dnsext-utils.
  • Statistic monitoring: Prometheus is supported.
  • Web API: the recent trend for server management is containers. When servers run in containers, the traditional signal scheme is not feasible. So, bowline provides web API for reading statistic, reloading, etc.

DNS transport

To protect privacy, the transport between DNS full resolvers and stub resolvers should be encrypted. The send-receive API of tls and quic is suitable to implement DoT (DNS over TLS) and DoQ (DNS over QUIC). However, the worker model of http2 and http3 is inefficient for DoH (DNS over HTTP). To emulate the send-receive API, runIO is implemented and provided from Internal module of http2. Unfortunately, I have no idea on how to implement runIO for http3 at this moment.

While verifying safety of http2 and quic, I noticed that not all cases of flow control are covered. The following should be implemented for stream numbers in a connection, amount of sending/receiving data in a connection and amount of sending/receiving data in a stream:

  • Telling the limit of receiving data to the peer in proper timing
  • Closing the connection if the receiving data reaches the limit
  • Sending data with the respect of the limit of sending data

To extract common patterns of flow-control, the network-control package is created. With network-control, http2 and quic have covered the all cases.

Refactoring and testing

The code for iterative queries was huge and monolithic. So, it was divided into multiple modules with the help of calligraphy which can visualize call-graph of functions.

dnsperf is used to measure server performance and to run stress testing. We noticed that stacks of Haskell lightweight threads consume huge memory. Their initial size of 1 KiB. When the limit are reached, they glow 33 KiB since the next chunk size is default to 32 KiB. In my opinion, this value is too big because threads might use only 2 KiB, for instance. So, we specify -kc2k (2 KiB) as an RTS option so that the size of stack glows 1KiB, 3 KiB, 5 KiB, 7 KiB and so on.

dug

dug is a command line interface for DNS queries. Of course, it can resolve records for a target domain using UDP as a stub resolver:

% dug www.iij.ad.jp aaaa
;; 2001:a7ff:5f01:1::a#53/UDP, Tx:42bytes, Rx:196bytes, 34usec
...
;; ANSWER SECTION:
www.iij.ad.jp.  300(5 mins) IN  AAAA    2001:240:bb81::10:180

The characteristics of dug are as follows:

  • Queries can be sent with DoT, DoQ and DoH if the -d option is specified.
  • Such a transport is automatically selected by parsing SVCB RRs if the -d auto is specified.
  • It can execute the iterative query algorithm used in bowline if the -i option is specified.

The followings are the new feature added in 2023FY:

  • tcp is added in addition to auto, doq, dot etc for the -d option.
  • The result of DNSSEC is displayed with colors if the --demo option is specified.
  • The query result is displayed in the JSON format if the --json option is specified.