View Source Erlang DNS Server

Serve DNS authoritative responses... with Erlang.

Build Status Module Version

Requirements

Erlang/OTP 27+

Building

To build:

make

To start fresh:

make fresh
make

Zones

Zones are loaded from JSON. Example JSON files are in the priv/ directory.

You can also write new systems to load zones by writing the zones directly to the zone cache using erldns_zone_cache:put_zone/1.

Configuration

An example configuration file can be found in erldns.example.config. Copy it to erldns.config and modify as needed.

Running

Launch directly

overmind start

To get an interactive Erlang REPL

./rebar3 shell

Build a distribution with and run the release

./rebar3 release
./_build/default/rel/erldns/bin/erldns foreground

Querying

Here are some queries to try:

dig -p 8053 @127.0.0.1 example.com a
dig -p 8053 @127.0.0.1 example.com cname
dig -p 8053 @127.0.0.1 example.com ns
dig -p 8053 @127.0.0.1 example.com mx
dig -p 8053 @127.0.0.1 example.com spf
dig -p 8053 @127.0.0.1 example.com txt
dig -p 8053 @127.0.0.1 example.com sshfp
dig -p 8053 @127.0.0.1 example.com soa
dig -p 8053 @127.0.0.1 example.com naptr

dig -p 8053 @127.0.0.1 -x 127.0.0.1 ptr

Performance

In our environment (DNSimple) we are seeing 30 to 65 µs handoff times to retrieve a packet from the UDP port and give it to a worker for processing. Your performance may vary, but given those measurements erl-dns is capable of handling between 15k and 30k questions per second. Please note: You may need to configure the number of workers available to handle traffic at higher volumes.

If you want to perform some benchmarks, see BENCHMARKING.md.

Design

The erldns_resolver module will attempt to find zone data in the zone cache. If you're embedding erl-dns in your application the easiest thing to do is to load the zone cache once the zone cache gen_server starts push an updated zone into the cache each time data changes.

To insert a zone, use erldns_zone_cache:put_zone({Name, Records}) where Name is a binary term such as <<"example.com">> and Records is a list of dns_rr records (whose definitions can be found in deps/dns/include/dns_records.hrl). The name of each record must be the fully qualified domain name (including the zone part).

Here's an example:

erldns_zone_cache:put_zone({
  <<"example.com">>, [
    #dns_rr{
      name = <<"example.com">>,
      type = ?DNS_TYPE_A,
      ttl = 3600,
      data = #dns_rrdata_a{ip = {1,2,3,4}}
    },
    #dns_rr{
      name = <<"www.example.com">>,
      type = ?DNS_TYPE_CNAME,
      ttl = 3600,
      data = #dns_rrdata_cname{dname = <<"example.com">>}
    }
  ]}).

AXFR Support

AXFR zone transfers are not currently implemented. The current "implementation" is just a stub.

Metrics

Folsom is used to gather runtime metrics and statistics.

There is an HTTP API for querying metric data available, you can read more about it at erldns_metrics

Here's an example script that shows how to get the output with curl and pass it through Python to format it in a pretty fashion. It assumes you have this API running on port 8082.

curl -s http://localhost:8082/ -H "Accept: application/json" | python -mjson.tool

[!IMPORTANT] Timing stats are given in microseconds.

Admin

There is an administrative API for querying the current zone cache and for basic control. You can read more about it at erldns_admin.

Tests

To run automated tests:

make test

This runs both EUnit tests and dialyzer.