CoreDNS とは?
[CoreDNS: DNS and Service Discovery] (https://coredns.io/)
2018 年現在 CNCF で Incubating な DNS サーバーです。
SkyDNS と互換性があり、 etcd などの多種のバックエンドを使って DNS をサービスすることができます。
ところで、社内で独自のカスタムを施した DNS サービスを作りたいと思ったことはないですか?
CoreDNS なら、 gRPC proxy 機能を用いて、独自のカスタマイズした DNS サービスに問合せを proxy することも可能です。
今回は簡単な例題を作成して、 CoreDNS gRPC proxy サービスの作成に入門してみましょう!
簡単な gRPC proxy サービスの例
今回は例題として、いかなるドメインの A 問合せに対しても単純に 127.0.0.1
を返すだけのサービスを作成してみましょう。
こちらが今回のサンプルです。
main.go
package main
import (
"context"
"fmt"
"github.com/coredns/coredns/pb"
"github.com/coredns/coredns/plugin/etcd/msg"
"github.com/miekg/dns"
"google.golang.org/grpc"
"log"
"net"
"os"
)
type DnsSample struct {}
func (ds *DnsSample) Query(ctx context.Context, in *pb.DnsPacket) (*pb.DnsPacket, error) {
m := new(dns.Msg)
err := m.Unpack(in.Msg)
if err != nil {
return nil, fmt.Errorf("failed to unpack msg: %v", err)
}
r := new(dns.Msg)
r.Question = m.Question
q := m.Question[0]
switch q.Qtype {
case dns.TypeA:
r.Id = m.Id
r.Response = true
serv := new(msg.Service)
r.Answer = []dns.RR{serv.NewA(q.Name, net.IPv4(127, 0, 0, 1))}
}
out, err := r.Pack()
if err != nil {
return nil, fmt.Errorf("failed to pack msg: %v", err)
}
return &pb.DnsPacket{Msg: out}, nil
}
func main() {
server := grpc.NewServer()
pb.RegisterDnsServiceServer(server, &DnsSample{})
listenPort, err := net.Listen("tcp", "0.0.0.0:1053")
if err != nil {
log.Println(err)
os.Exit(1)
}
server.Serve(listenPort)
}
gRPC の定義は、 github.com/coredns/coredns/pb
にありますので、これを import して用います。
dns.proto
syntax = "proto3";
package coredns.dns;
option go_package = "pb";
message DnsPacket {
bytes msg = 1;
}
service DnsService {
rpc Query (DnsPacket) returns (DnsPacket);
}
この rpc Query
を自分で実装することで独自カスタムができます。
このように CoreDNS 側とやり取りできるデータはただの byte 列です。
dns.Msg
を用いて、 Unpack()
, Pack()
することができるので、それで DNS のプロトコルをパースすることができます。
具体的にはコードを読んでみてください。
gRPC proxy を行う設定
CoreDNS は Corefile
というファイルに設定を記述します。
下記のように記述することで、 DNS の問い合わせを今回作成する独自の DNS サービスに proxy することができるようになります。
Corefile
.:53 {
proxy . 127.0.0.1:1053 {
protocol grpc insecure
}
debug
log
}
動作確認
CoreDNS を起動
設定ファイルであるCorefile
が存在するディレクトリで起動します。
$ sudo coredns
gRPC proxy サービスを起動
今回作成した main.go
を起動します。
$ go build main.go
問合せしてみる
適当なドメインへの A 問合せに対して、 127.0.0.1
を返しています!
$ dig +short A @127.0.0.1 "test.com"
127.0.0.1
Let's hack!
今回の記事では CoreDNS の gRPC proxy で動作する、独自 DNS サービスの例題を実装してみました。
これらの例題をもとに、バックエンドデータベース、レコードデータのフォーマット、アルゴリズム、お好きなようにカスタマイズしてみてください😉