CoreDNS自建安全的DNS server

DNS一般是通过UDP以明文的方式查询,这将给中间人留下了很多攻击的可能。为了进一步加强网络安全,可以使用CoreDNS,通过DNS over TLS(DoT)来实现相对更安全的DNS server。


CoreDNS

CoreDNS是一个由Go语言写成的,高度灵活的DNS服务器。常被用来给k8s集群做服务发现。

这里选择CoreDNS的原因是:

  1. Docker支持较好。有官方的Docker镜像,而不用自己维护Dockerfile或者依赖社区中由个人维护的镜像。且官方镜像使用不算太复杂。
  2. As Code。代码化的好处我想不需要多解释了。
  3. 社区活跃。这一点也许是得益于k8s,导致这个工具的各方面资料稍微多一些。
  4. 较为灵活。CoreDNS拥有不少插件,可以假设CoreDNS能更灵活的应对更多复杂的场景。
  5. 上手简单。配置的可读性较高,较为表意。而且本地调试也非常容易。

DoT

首先DNS over TLS是通过或者可以通过TLS来加密DNS通信的。这样的加密阻止了中间人窃听或篡改DNS查询,从而提高了网络的安全性。

假如,直接使用不经过加密的普通UDP的DNS查询,那么就可能出现以下情景:

  1. 你的运营商清楚的知道你每天访问了哪些网站,即使这些网站你并不都能访问。
  2. 你的网络访问可能被代理。虽然也许你的浏览器并没有爆出警告,但是我们应该牢记CNNIC证书的教训。
  3. 你的网络访问可能被负优化。比如虽然结果仍然是同一个网站的服务器,但结果却是此网站位于荷兰的CDN节点。

具体实施

首先,我们需要选择一个可信的上游DNS server,不论是8.8.8.8还是114.114.114.114都好。关键是你愿意信任,或者至少相信对方不至于拿着你的这一点点信息作恶。其次是最好能支持DoT或者DoH。(当然,如果你说你信任你的运行商,以及信任传输过程的中间人。那我个人的建议是点击关闭此网页

接下来就可以开始写Corefile和Dockerfile了。

首先是Corefile,其实就非常简单:

.:53 {
    forward . tls://8.8.8.8 {
        tls_servername dns.google
    }
    log
    errors
}

然后是Dockerfile,也非常简单,甚至不需要dockerfile,直接-v用volume挂进去也是可以的:

FROM coredns/coredns

ADD Corefile ./

唯一注意的是,CoreDNS配置里的.53是UDP端口,所有docker运行的时候应该是-p 53:53/udp


最后一公里

假如你的CoreDNS部署在一台VPS上,那么请警惕“最后一公里”的问题。这里要么就直接把CoreDNS部署到内网,要么就需要将VPS上的CoreDNS的DNS改成只听DoT的请求:

tls://.:1443 {
    tls /certs/fullchain.pem /certs/privkey.pem
    forward . tls://8.8.8.8 {
        tls_servername dns.google
    }
    log
    errors
}

并且记得将你的证书映射进container中。

然后依然需要在内网起一个CoreDNS的服务,来和你自己VPS上的服务对接。


最后这一篇博客更多的是给一个CoreDNS的基础。接下来将写一篇基于于国内网络和透明代理场景下运用CoreDNS实现DNS服务搭建。