CoreDNS笔记

因为项目的原因需要在客户端启动DNS服务,拦截本机DNS请求,考察了一下开源的DNS Server项目,适合在Windows下使用的只有CoreDNS。

说明

CoreDNS的项目地址
https://coredns.io
https://github.com/coredns/coredns

这是go语言写的,所以默认支持大部分平台,在windows下有一些瑕疵(下面会说),但是总体已经是功能比较完整的一个DNS服务端实现。

使用

CoreDNS的使用很简单,coredns.exe配合一个Corefile配置文件直接就可以运行。配置文件的格式类似于

# 监听默认端口(53), .表示所有域名
. {
  # 绑定lo网口,这样启动是静默的,否则默认绑定0.0.0.0会弹出windows防火墙
  bind 127.0.0.1

  # hosts插件,自定义域名的解析,解析的域名少就直接用hosts插件完成需求,如果有大量自定义域名解析建议用file插件使用 符合RFC 1035规范的DNS解析配置文件
  hosts {
    10.6.6.2 somewhere.com
    10.6.6.3 ip.com
    10.10.0.2 m.baidu.com
    # ttl
    ttl 60
    # 继续执行
    fallthrough
  }
  # 将走到这一步的所有解析请求转发给192.168.10.1,这里可以配置多个地址,转发时会同时对多个地址发起转发
  forward . 192.168.10.1:53

  # 重载hosts配置 windows下不支持
  # reload 10s

  # 输出错误
  errors

  # 输出日志
  #log . "{remote}:{port} - {>id} \"{proto} Request: {name} {type} {rsize} {rcode}\""
}

在命令行执行下面的命令启动服务

coredns.exe -conf path\to\Corefile

然后新开一个窗口,验证dns服务是否正常。注意这里第二个参数就是DNS服务器地址,要用127.0.0.1不能用localhost

nslookup www.baidu.com 127.0.0.1

编译和定制

在Goland里可以直接通过go mod tidy && go build编译,在clone的代码上直接编译,产生的coredns.exe文件有60M。如果要减小文件尺寸,可以去掉一些不必要的插件。
插件的配置文件在plugin.cfg,可以将其中和k8s, aws相关的插件屏蔽,以下是我屏蔽插件后的列表

metadata:metadata
cancel:cancel
tls:tls
reload:reload
nsid:nsid
bufsize:bufsize
root:root
bind:bind
debug:debug
trace:trace
ready:ready
health:health
pprof:pprof
#prometheus:metrics
errors:errors
log:log
dnstap:dnstap
local:local
dns64:dns64
acl:acl
any:any
chaos:chaos
loadbalance:loadbalance
cache:cache
rewrite:rewrite
dnssec:dnssec
autopath:autopath
template:template
transfer:transfer
hosts:hosts
#route53:route53
#azure:azure
#clouddns:clouddns
#k8s_external:k8s_external
#kubernetes:kubernetes
file:file
auto:auto
secondary:secondary
etcd:etcd
loop:loop
forward:forward
grpc:grpc
#erratic:erratic
whoami:whoami
on:github.com/coredns/caddy/onevent
sign:sign

然后执行下面的命令就可以重新编译

# 根据plugin.cfg更新插件配置
go generate
# 编译
go build

这样产生的coredns.exe只有25M大小
通过coredns.exe -plugins命令可以看到包含插件的情况

coredns.exe -plugins
Server types:
  dns

Caddyfile loaders:
  flag
  default

Other plugins:
  dns.acl
  dns.any
  dns.auto
  dns.autopath
  dns.bind
  dns.bufsize
  dns.cache
  dns.cancel
  dns.chaos
  dns.debug
  dns.dns64
  dns.dnssec
  dns.dnstap
  dns.errors
  dns.etcd
  dns.file
  dns.forward
  dns.grpc
  dns.health
  dns.hosts
  dns.loadbalance
  dns.local
  dns.log
  dns.loop
  dns.metadata
  dns.nsid
  dns.pprof
  dns.prometheus
  dns.ready
  dns.reload
  dns.rewrite
  dns.root
  dns.secondary
  dns.sign
  dns.template
  dns.tls
  dns.trace
  dns.transfer
  dns.whoami
  on

修改

因为要记录解析结果,但是CoreDNS的日志输出不包含解析结果,需要自己动手修改。这个修改在forward.go
在 ServeDNS() 方法下,在下面两行之前

		w.WriteMsg(ret)
		return 0, nil

增加

		for _, a := range ret.Answer {
			if a.Header().Rrtype == dns.TypeA {
				for _, b := range ret.Question {
					log.Printf("%v ", b.Name)
				}
				log.Printf("IP: %v\n", a.(*dns.A).A.String())
			} else if a.Header().Rrtype == dns.TypeAAAA {
				for _, b := range ret.Question {
					log.Printf("%v ", b.Name)
				}
				log.Printf("IP: %v\n", a.(*dns.AAAA).AAAA.String())
			} else if a.Header().Rrtype == dns.TypeCNAME {
				for _, b := range ret.Question {
					log.Printf("%v ", b.Name)
				}
				log.Printf("CNAME: %v\n", a.(*dns.CNAME).Target)
			} else if a.Header().Rrtype == dns.TypePTR {
				log.Printf("PTR: %v\n", a.(*dns.PTR).Ptr)
			} else {
				log.Printf("Type: %v\n", a.Header().Rrtype)
			}
		}

posted on 2020-12-20 14:50  Milton  阅读(1797)  评论(0编辑  收藏  举报

导航