Erlang-based DNS Server(起着跟bind一样的作用)
Serve DNS authoritative responses...with Erlang.
Building
To build clean:
./build.sh
If you've already built once and just want to recompile the erl-dns source:
./rebar compile
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.config.example.
Copy it to erldns.config and modify as needed.
Running
Launch directly:
erl -config erldns.config -pa ebin -pa deps/**/ebin -s erldns
Or use Foreman:
foreman start
Querying
Here are some queries to try:
dig -p8053 @127.0.0.1 example.com a
dig -p8053 @127.0.0.1 example.com cname
dig -p8053 @127.0.0.1 example.com ns
dig -p8053 @127.0.0.1 example.com mx
dig -p8053 @127.0.0.1 example.com spf
dig -p8053 @127.0.0.1 example.com txt
dig -p8053 @127.0.0.1 example.com sshfp
dig -p8053 @127.0.0.1 example.com soa
dig -p8053 @127.0.0.1 example.com naptr
dig -p8053 @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 retreive 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.
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">>}
}
]}).
Metrics
Folsom is used to gather runtime metrics and statistics.
There is an HTTP API for querying metric data available at https://github.com/dnsimple/erldns-metrics
Admin
There is a administrative API for querying the current zone cache and for basic control. You can find it in https://github.com/dnsimple/erldns-admin
from https://github.com/dnsimple/erldns
----
Erlang/OTP based DNS server
----
Erlang/OTP based DNS server
erlang-dns
Erlang/OTP DNS server
erlang-dns is an authorative non recursive DNS server I am writing for my site http://www.domain-name-registration.co.za.
The idea is to have a simple DNS server that can be configured with arbitrary Zones via simple Erlang modules. It's up to you whether the Zone is defined in some file or a DB for example. As long as the module returns a zone as a list of resource records erlang-dns can serve it up.
In addition, erlang-dns supports custom extensions to enhance or entirely change the server's behaviour.
Releases
- 2014-01-11
v0.1-alpha
- First version that conforms to RFC1034 examples
Example
-module(my_zone_provider).
-export([get_zone/1]).
-include_lib("kernel/src/inet_dns.hrl").
get_zone(_Args) ->
%% Fetch the Zone from a file, the DB, ...
%% Here we just hardcode it
{ok, [
#dns_rr{domain="bot.co.za", type=soa, data={
"ns1.bot.co.za",
"hc.vst.io",
870611, %serial
1800, %refresh every 30 min
300, %retry every 5 min
604800, %expire after a week
86400 %minimum of a day
}
},
#dns_rr{domain="bot.co.za", type=ns, data="ns1.bot.co.za"},
#dns_rr{domain="bot.co.za", type=ns, data="ns2.bot.co.za"},
#dns_rr{domain="www.bot.co.za", type=cname, data="bot.co.za"},
#dns_rr{domain="bot.co.za", type=a, data={127,0,0,1}}
]}.
Then, bring up the server with
erl -pa ./ebin -s edns
and register your zone provider.edns:register_zone_provider("bot.co.za", {my_zone_provider, get_zone, []}).
If you change and recompile
my_zone_provider
you can flush the zone withedns:flush("bot.co.za").
without restarting the server.
Also, please have a look at the-end-to end test scenario for an example of how to setup the included
src/simple_backend.erl
zone provider module.
The
simple_backend
consists essentially of only the following two lines:get_zone(Zone) ->
{ok, Zone}.
Instead of writing the
my_zone_provider
above, you could have achieved the same result with:Eshell V5.10.2 (abort with ^G)
1> ends:register_zone_provider("bot.co.za", {simple_backend, get_zone, [
#dns_rr{domain="bot.co.za", type=soa, data={
"ns1.bot.co.za",
"hc.vst.io",
870611, %serial
1800, %refresh every 30 min
300, %retry every 5 min
604800, %expire after a week
86400 %minimum of a day
}
},
#dns_rr{domain="bot.co.za", type=ns, data="ns1.bot.co.za"},
#dns_rr{domain="bot.co.za", type=ns, data="ns2.bot.co.za"},
#dns_rr{domain="www.bot.co.za", type=cname, data="bot.co.za"},
#dns_rr{domain="bot.co.za", type=a, data={127,0,0,1}}
]}).
Extensions
Extensions live in the
priv/extensions
folder. Have a look at the simple_stats
extension that counts the number of DNS requests.
Extensions can consist of custom resolvers and OTP servers/supervisors.
Custom Resolvers
By default, queries are processed by
ed_query_resolver
, however you can implement a custom resolver to augment or swap out ed_query_resolver
entirely.edns.app.src
specifies what resolver(s) to use:{env, [
{port, 1051},
{resolvers, [ed_query_resolver, simple_stats_resolver]}
]}
ed_udp_handler_server
foldl
s over all resolvers to arrive at a DNS query response.
The
simple_stats_resolver
is a passthrough resolver that does not modify the repsonse. All it does is to notify simple_stats_server
that another query has arrived.
Another example usecase of a custom resolver is one that looks up the synopsis of a Wikipedia article and returns it in a TXT record.
Custom OTP servers/supervisors
Modules in the
extensions/...
directory that implement either the gen_server
or supervisor
behaviour are automatically started and supervised by ed_extension_sup
. This is useful if your custom resolvers need to maintain state.Tests
To run the end to end test execute
make e2e
.System Architecture
Please see the wiki https://github.com/hcvst/erlang-dns/wiki/Architecture
No comments:
Post a Comment