-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
529 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,3 +12,7 @@ | |
|
||
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 | ||
.glide/ | ||
|
||
.tmp/ | ||
*.tar.gz | ||
coredns |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,113 @@ | ||
# coredns-amazondns | ||
Amazon DNS plugin for CoreDNS | ||
The *amazondns* plugin behaves **Authoritative name server** using [Amazon DNS Server](https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_DHCP_Options.html#AmazonDNS) as the backend. | ||
|
||
The Amazon DNS server is used to resolve the DNS domain names that you specify in a private hosted zone in Route 53. However, the server acts as **Caching name server**. Although CoreDNS has [proxy plugin](https://github.com/coredns/coredns/tree/master/plugin/proxy) and we can configure Amazon DNS server as the backend, it can't be Authoritative name server. In my case, Authoritative name server is required to handle delegated responsibility for the subdomain. That's why I created this plugin. | ||
|
||
## Name | ||
|
||
*amazondns* - enables serving Authoritative name server using Amazon DNS Server as the backend. | ||
|
||
## Syntax | ||
|
||
```txt | ||
amazondns ZONE [ADDRESS] { | ||
soa RR | ||
ns RR | ||
nsa RR | ||
} | ||
``` | ||
|
||
* **ZONE** the zone scope for this plugin. | ||
* **ADDRESS** defines the Amazon DNS server address specifically. | ||
If no **ADDRESS** entry, this plugin resovles it automatically using [Instance Metadata](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html). | ||
* **soa** **RR** SOA record with [RFC 1035](https://tools.ietf.org/html/rfc1035#section-5) style. | ||
* **ns** **RR** NS record(s) with [RFC 1035](https://tools.ietf.org/html/rfc1035#section-5) style. | ||
* **nsa** **RR** A record(s) for the NS(s) with [RFC 1035](https://tools.ietf.org/html/rfc1035#section-5) style. | ||
|
||
## Examples | ||
|
||
Create your Route 53 private hostead zone with `sub.example.org` and attach your VPC. Then add A record for `test.sub.example.org` into the zone. | ||
|
||
Next, boot EC2 instance and deploy CoreDNS binary, and configure CoreDNS config file as below. | ||
|
||
```txt | ||
. { | ||
amazondns sub.example.org { | ||
soa "sub.example.org 60 IN SOA ns1.sub.example.org hostmaster.sub.example.org (1 7200 900 1209600 86400)" | ||
ns "sub.example.org 60 IN NS ns1.sub.example.org" | ||
ns "sub.example.org 60 IN NS ns2.sub.example.org" | ||
nsa "ns1.sub.example.org 60 IN A 192.168.0.1" | ||
nsa "ns2.sub.example.org 60 IN A 192.168.0.2" | ||
} | ||
} | ||
``` | ||
|
||
Boot CoreDNS and check it how it works. | ||
|
||
The `test.sub.example.org` is resolved with *AUTHORITY SECTION* and *ADDITIONAL SECTION* as below. | ||
|
||
```bash | ||
> dig @localhost test.sub.example.org +norecurse | ||
|
||
; <<>> DiG 9.11.1 <<>> @localhost test.sub.example.org +norecurse | ||
; (1 server found) | ||
;; global options: +cmd | ||
;; Got answer: | ||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28681 | ||
;; flags: qr aa ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 3 | ||
;; OPT PSEUDOSECTION: | ||
; EDNS: version: 0, flags:; udp: 4096 | ||
; COOKIE: 23246de45b4a3601 (echoed) | ||
;; QUESTION SECTION: | ||
;test.sub.example.org. IN A | ||
;; ANSWER SECTION: | ||
test.sub.example.org. 60 IN A 10.0.0.10 | ||
;; AUTHORITY SECTION: | ||
sub.example.org. 60 IN NS ns1.sub.example.org. | ||
sub.example.org. 60 IN NS ns2.sub.example.org. | ||
;; ADDITIONAL SECTION: | ||
ns1.sub.example.org. 60 IN A 192.168.0.1 | ||
ns2.sub.example.org. 60 IN A 192.168.0.2 | ||
;; Query time: 12 msec | ||
;; SERVER: 127.0.0.1#53(127.0.0.1) | ||
;; WHEN: Tue Feb 20 15:11:55 JST 2018 | ||
;; MSG SIZE rcvd: 146 | ||
``` | ||
Also it can return NS record(s) for subdomain as below. | ||
```bash | ||
> dig @localhost sub.example.org ns | ||
; <<>> DiG 9.11.1 <<>> @localhost sub.example.org ns +norecurse | ||
; (1 server found) | ||
;; global options: +cmd | ||
;; Got answer: | ||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2719 | ||
;; flags: qr aa ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 3 | ||
;; OPT PSEUDOSECTION: | ||
; EDNS: version: 0, flags:; udp: 4096 | ||
; COOKIE: c1c3332966dba8fd (echoed) | ||
;; QUESTION SECTION: | ||
;sub.example.org. IN NS | ||
;; ANSWER SECTION: | ||
sub.example.org. 60 IN NS ns1.sub.example.org. | ||
sub.example.org. 60 IN NS ns2.sub.example.org. | ||
;; ADDITIONAL SECTION: | ||
ns1.sub.example.org. 60 IN A 192.168.0.1 | ||
ns2.sub.example.org. 60 IN A 192.168.0.2 | ||
;; Query time: 1 msec | ||
;; SERVER: 127.0.0.1#53(127.0.0.1) | ||
;; WHEN: Tue Feb 20 15:08:27 JST 2018 | ||
;; MSG SIZE rcvd: 125 | ||
``` | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package amazondns | ||
|
||
import ( | ||
"github.com/coredns/coredns/plugin" | ||
"github.com/coredns/coredns/request" | ||
|
||
"github.com/miekg/dns" | ||
"golang.org/x/net/context" | ||
) | ||
|
||
// AmazonDNS represents a plugin instance that can proxy requests to AmazonDNS. | ||
type AmazonDNS struct { | ||
Next plugin.Handler | ||
|
||
client *dns.Client | ||
zones []string | ||
zoneMap map[string]*Zone | ||
} | ||
|
||
type Zone struct { | ||
zone string | ||
dns string | ||
soa dns.RR | ||
ns []dns.RR | ||
nsa []dns.RR | ||
} | ||
|
||
// ServeDNS implements plugin.Handler. | ||
func (ad AmazonDNS) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { | ||
state := request.Request{W: w, Req: r} | ||
name := state.Name() | ||
|
||
key := plugin.Zones(ad.zones).Matches(name) | ||
if key == "" { | ||
return plugin.NextOrFailure(ad.Name(), ad.Next, ctx, w, r) | ||
} | ||
zone := ad.zoneMap[key] | ||
|
||
qtype := state.QType() | ||
|
||
m := new(dns.Msg) | ||
m.SetReply(r) | ||
m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true | ||
|
||
L: | ||
switch qtype { | ||
case dns.TypeA: | ||
for _, nsa := range zone.nsa { | ||
if name == nsa.Header().Name { | ||
m.Answer = []dns.RR{nsa} | ||
m.Ns = zone.ns | ||
m.Rcode = dns.RcodeSuccess | ||
break L | ||
} | ||
} | ||
fallthrough | ||
case dns.TypeAAAA: | ||
fallthrough | ||
case dns.TypeCNAME: | ||
// Need recursive mode for getting record from AmazonDNS | ||
r.MsgHdr.RecursionDesired = true | ||
resp, _, err := ad.client.Exchange(r, zone.dns) | ||
|
||
if err != nil { | ||
return dns.RcodeServerFailure, err | ||
} | ||
|
||
m.Answer = resp.Answer | ||
m.Rcode = resp.Rcode | ||
|
||
// Overwrite authority and additional section | ||
if len(m.Answer) > 0 { | ||
m.Ns = zone.ns | ||
m.Extra = zone.nsa | ||
} else { | ||
handleNotFound(zone, name, m) | ||
} | ||
case dns.TypeNS: | ||
if name == zone.soa.Header().Name { | ||
m.Answer = zone.ns | ||
m.Extra = zone.nsa | ||
m.Rcode = dns.RcodeSuccess | ||
} else { | ||
handleNotFound(zone, name, m) | ||
} | ||
case dns.TypeSOA: | ||
if name == zone.soa.Header().Name { | ||
m.Answer = []dns.RR{zone.soa} | ||
m.Ns = zone.ns | ||
} else { | ||
handleNotFound(zone, name, m) | ||
} | ||
default: | ||
handleNotFound(zone, name, m) | ||
} | ||
|
||
state.SizeAndDo(m) | ||
m, _ = state.Scrub(m) | ||
w.WriteMsg(m) | ||
return dns.RcodeSuccess, nil | ||
} | ||
|
||
func handleNotFound(zone *Zone, name string, m *dns.Msg) { | ||
m.Ns = []dns.RR{zone.soa} | ||
|
||
if name == zone.soa.Header().Name { | ||
m.Rcode = dns.RcodeSuccess | ||
return | ||
} | ||
for _, ns := range zone.ns { | ||
if name == ns.Header().Name { | ||
m.Rcode = dns.RcodeSuccess | ||
return | ||
} | ||
} | ||
for _, nsa := range zone.nsa { | ||
if name == nsa.Header().Name { | ||
m.Rcode = dns.RcodeSuccess | ||
return | ||
} | ||
} | ||
|
||
// Error | ||
m.Rcode = dns.RcodeNameError | ||
} | ||
|
||
func (ad *AmazonDNS) fillResponse(state request.Request, m *dns.Msg) { | ||
} | ||
|
||
// Name implements the Handler interface. | ||
func (ad AmazonDNS) Name() string { return "amazondns" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#!/bin/sh | ||
|
||
VERSION=0.1 | ||
TAG=master | ||
|
||
if [ "$1" = "" ]; then | ||
docker run --rm \ | ||
-v $(pwd):/go/src/github.com/wadahiro/coredns-amazondns \ | ||
-v $(pwd)/.tmp:/go \ | ||
-w /go/src/github.com/wadahiro/coredns-amazondns \ | ||
golang:1.9 ./build.sh $TAG | ||
else | ||
echo "Building CoreDNS:$1 with amazondns..." | ||
|
||
go get github.com/coredns/coredns | ||
cd /go/src/github.com/coredns/coredns | ||
|
||
git reset --hard HEAD | ||
git clean -f | ||
|
||
git checkout $1 | ||
if [ "$?" -ne 0 ]; then | ||
echo "Invalid tag: $1" | ||
exit 1 | ||
fi | ||
|
||
sed -i -e "/^route53:route53$/i amazondns:github.com/wadahiro/coredns-amazondns" plugin.cfg | ||
|
||
if [ "$?" -ne 0 ]; then | ||
echo "Failed" | ||
exit 1 | ||
fi | ||
|
||
cat plugin.cfg | ||
|
||
go generate | ||
#make | ||
go build | ||
|
||
cp coredns /go/src/github.com/wadahiro/coredns-amazondns/ | ||
tar cvzf coredns-amazondns-$VERSION.tar.gz coredns | ||
mv coredns-*.tar.gz /go/src/github.com/wadahiro/coredns-amazondns/ | ||
fi | ||
|
Oops, something went wrong.