middleware/etcd: reverse addresses (#162)

* middleware/etcd: reverse addresses

Implement reverse (PTR) addresses. Update the documentation on how to
configure test. Added tests as well.

Fixes: #157 #159

* Cleanup readme a little
This commit is contained in:
Miek Gieben 2016-06-08 10:29:46 +01:00
parent 3165084a7b
commit 713f10f6af
6 changed files with 79 additions and 5 deletions

View file

@ -72,3 +72,48 @@ This is the default SkyDNS setup, with everying specified in full:
proxy . 8.8.8.8:53 8.8.4.4:53
}
~~~
### Reverse zones
Reverse zones are supported. You need to make CoreDNS aware of the fact that you are also
authoritative for the reverse. For instance if you want to add the reverse for 10.0.0.0/24, you'll
need to add the zone `10.in-addr.arpa` to the list of zones (the fun starts with reverse IPv6 zones
in the ip6.arpa domain). Showing a snippet of a Corefile:
~~~
etcd skydns.local 10.in-addr.arpa {
stubzones
...
~~~
Next you'll need to populate the zone with reverse records, here we add a reverse for
10.0.0.127 pointing to reverse.skydns.local.
~~~
% curl -XPUT http://127.0.0.1:4001/v2/keys/skydns/arpa/in-addr/10/0/0/127 \
-d value='{"host":"reverse.skydns.local."}'
~~~
Querying with dig:
~~~
% dig @localhost -x 10.0.0.127 +short
reverse.atoom.net.
~~~
Or with *debug* queries enabled:
~~~
% dig @localhost -p 1053 o-o.debug.127.0.0.10.in-addr.arpa. PTR
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;o-o.debug.127.0.0.10.in-addr.arpa. IN PTR
;; ANSWER SECTION:
127.0.0.10.in-addr.arpa. 300 IN PTR reverse.atoom.net.
;; ADDITIONAL SECTION:
127.0.0.10.in-addr.arpa. 300 CH TXT "reverse.atoom.net.:0(10,0,,false)[0,]"
~~~

View file

@ -58,6 +58,8 @@ func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
records, debug, err = e.TXT(zone, state)
case "CNAME":
records, debug, err = e.CNAME(zone, state)
case "PTR":
records, debug, err = e.PTR(zone, state)
case "MX":
records, extra, debug, err = e.MX(zone, state)
case "SRV":

View file

@ -305,6 +305,21 @@ func (e Etcd) CNAME(zone string, state middleware.State) (records []dns.RR, debu
return records, debug, nil
}
// PTR returns the PTR records, only services that have a domain name as host are included.
func (e Etcd) PTR(zone string, state middleware.State) (records []dns.RR, debug []msg.Service, err error) {
services, debug, err := e.records(state, true)
if err != nil {
return nil, debug, err
}
for _, serv := range services {
if ip := net.ParseIP(serv.Host); ip == nil {
records = append(records, serv.NewPTR(state.QName(), serv.Host))
}
}
return records, debug, nil
}
func (e Etcd) TXT(zone string, state middleware.State) (records []dns.RR, debug []msg.Service, err error) {
services, debug, err := e.records(state, false)
if err != nil {

View file

@ -15,20 +15,22 @@ var services = []*msg.Service{
{Host: "10.0.0.1", Port: 8080, Key: "a.server1.prod.region1.skydns.test."},
{Host: "10.0.0.2", Port: 8080, Key: "b.server1.prod.region1.skydns.test."},
{Host: "::1", Port: 8080, Key: "b.server6.prod.region1.skydns.test."},
// Unresolvable internal name
// Unresolvable internal name.
{Host: "unresolvable.skydns.test", Key: "cname.prod.region1.skydns.test."},
// priority
// Priority.
{Host: "priority.server1", Priority: 333, Port: 8080, Key: "priority.skydns.test."},
// Subdomain
// Subdomain.
{Host: "sub.server1", Port: 0, Key: "a.sub.region1.skydns.test."},
{Host: "sub.server2", Port: 80, Key: "b.sub.region1.skydns.test."},
{Host: "10.0.0.1", Port: 8080, Key: "c.sub.region1.skydns.test."},
// Cname loop
// Cname loop.
{Host: "a.cname.skydns.test", Key: "b.cname.skydns.test."},
{Host: "b.cname.skydns.test", Key: "a.cname.skydns.test."},
// Nameservers.
{Host: "10.0.0.2", Key: "a.ns.dns.skydns.test."},
{Host: "10.0.0.3", Key: "b.ns.dns.skydns.test."},
// Reverse.
{Host: "reverse.example.com", Key: "1.0.0.10.in-addr.arpa."}, // 10.0.0.1
}
var dnsTestCases = []test.Case{
@ -198,4 +200,9 @@ var dnsTestCases = []test.Case{
Qname: "skydns_extra.test.", Qtype: dns.TypeSOA,
Answer: []dns.RR{test.SOA("skydns_extra.test. 300 IN SOA ns.dns.skydns_extra.test. hostmaster.skydns_extra.test. 1460498836 14400 3600 604800 60")},
},
// Reverse lookup
{
Qname: "1.0.0.10.in-addr.arpa.", Qtype: dns.TypePTR,
Answer: []dns.RR{test.PTR("1.0.0.10.in-addr.arpa. 300 PTR reverse.example.com.")},
},
}

View file

@ -102,6 +102,11 @@ func (s *Service) NewTXT(name string) *dns.TXT {
return &dns.TXT{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: s.Ttl}, Txt: split255(s.Text)}
}
// NewPTR returns a new PTR record based on the Service.
func (s *Service) NewPTR(name string, target string) *dns.PTR {
return &dns.PTR{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: s.Ttl}, Ptr: dns.Fqdn(target)}
}
// NewNS returns a new NS record based on the Service.
func (s *Service) NewNS(name string) *dns.NS {
host := targetStrip(dns.Fqdn(s.Host), s.TargetStrip)

View file

@ -37,7 +37,7 @@ func init() {
PathPrefix: "skydns",
Ctx: context.Background(),
Inflight: &singleflight.Group{},
Zones: []string{"skydns.test.", "skydns_extra.test."},
Zones: []string{"skydns.test.", "skydns_extra.test.", "in-addr.arpa."},
Client: etcdc.NewKeysAPI(cli),
}
}