DNS Monitor 环境搭建(二)

作者:znn

原文地址:https://secvul.com/topics/1121.html


利用性能强大的CoreDNS和非关系型数据库MongoDB,修改自带的插件,成功解决了上篇文章 “DNS Monitor 环境搭建(一)https://secvul.com/topics/979.html” 留下的一些问题。

0x01 MongoDB搭建

Ubuntu 一键安装:

apt-get install mongodb

安装后默认开启mongodb服务,这里先关掉服务。
自定义MongoDB配置文件:

ork=true
dbpath = ./db/
logpath = ./log/mongodb.log
logappend = true
bind_ip = 127.0.0.1
port = 27018
journal = true
nohints = true
nohttpinterface = true

然后直接mongod –config mongodb.conf开启MongoDB服务。
客户端用mongo –port 27018测试是否正常运行。

0x02 Golang 语言环境

Ubuntu 一键安装:

apt-get install golang

也可以参考官方文档golang.org下载二进制包安装(需扶墙)。
执行go env查看go环境变量是否正常。

0x03 CoreDNS 安装

coredns.io 官方给出的安装说明:

$ export GOPATH=${GOPATH-~/go}
$ mkdir -p $GOPATH/src/github.com/coredns
$ cd $GOPATH/src/github.com/coredns/
$ git clone https://github.com/coredns/coredns.git
$ cd coredns
$ make CHECKS= godeps all

这里注意我们在执行 make CHECKS= godeps all 之前要修改代码才能解决上篇文章留下的几个问题。
参考官方文档,这里直接修改plugin/whoami/whoami.go插件,代码内容为对每条应用whoami插件的dns请求,返回一个record,其内容为客户端来源ip,并将整个记录存储在MongoDB服务器中。修改完整的 whoami.go 代码如下:

// Package whoami implements a plugin that returns details about the resolving
// querying it.
package whoami
import (
 "net"
// "strconv"
 "gopkg.in/mgo.v2"
 "fmt"
 "time"
// add
 "github.com/coredns/coredns/request"
 "github.com/miekg/dns"
 "golang.org/x/net/context"
)
// Whoami is a plugin that returns your IP address, port and the protocol used for connecting
// to CoreDNS.
type Whoami struct{}
//mongodb data struct
type DNSQueryData struct {
 Qip string
 Qaddress string
 Qtime time.Time
}
//init db session with mongodb config
var (
 session, err = mgo.Dial("127.0.0.1:27018")
 db = session.DB("coredns").C("Qrecoders")
)
// ServeDNS implements the plugin.Handler interface.
func (wh Whoami) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 state := request.Request{W: w, Req: r}
//add
//Standard out info
//and use MongoDB
 fmt.Println("Source Ip:", state.IP(), "Address:", state.QName(), "Time:", time.Now())
 err = db.Insert(&DNSQueryData{state.IP(), state.QName(), time.Now()})
 if err != nil {
 println(err)
 }
//
 a := new(dns.Msg)
 a.SetReply(r)
 a.Compress = true
 a.Authoritative = true
 ip := state.IP()
 var rr dns.RR
 switch state.Family() {
 case 1:
 rr = new(dns.A)
 rr.(*dns.A).Hdr = dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeA, Class: dns.ClassINET}
 rr.(*dns.A).A = net.ParseIP(ip).To4()
 case 2:
 rr = new(dns.AAAA)
 rr.(*dns.AAAA).Hdr = dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeAAAA, Class: dns.ClassINET}
 rr.(*dns.AAAA).AAAA = net.ParseIP(ip)
 }
/*
 srv := new(dns.SRV)
 srv.Hdr = dns.RR_Header{Name: "_" + state.Proto() + "." + state.QName(), Rrtype: dns.TypeSRV, Class: state.QClass()}
 if state.QName() == "." {
 srv.Hdr.Name = "_" + state.Proto() + state.QName()
 }
 port, _ := strconv.Atoi(state.Port())
 srv.Port = uint16(port)
 srv.Target = "."
*/
 //a.Extra = []dns.RR{rr, srv}
 a.Answer = []dns.RR{rr}
 state.SizeAndDo(a)
 a, _ = state.Scrub(a)
 w.WriteMsg(a)
 //return 0, nil
 return dns.RcodeSuccess, nil
}
// Name implements the Handler interface.
func (wh Whoami) Name() string { return "whoami" }

代码为了尽量少的修改原始插件,这里将mongodb配置信息直接写死在文件中了,也可以对whoami插件添加参数来引用配置信息。
执行 make CHECKS= godeps all 编译我们修改过的项目代码,并在当前目录成功生成coredns二进制文件。
这里遇到两个坑:

  • go get 需要扶墙,不然等死你也不成功,挂代理什么的也不行,直接在VPS上编译吧。
    开始试了几个VPS均失败,发现单核CPU会编译出错。

0x04 测试 CoreDNS

OK,到这一步前面环境搭建没问题的话,接下来测试coredns。
添加coredns 配置文件:

dns.bypass.world:53 {
 whoami
}

启动mongodb:

mongod --config mongodb.conf

执行coredns:

./coredns -conf coredns.conf

在上篇文章中我们做了如下DNS解析:

Type  Name               Value
A     ns.bypass.world    119.23.236.88
NS    dns.bypass.world   ns.bypass.world

现在我们同样用这个NS记录,然后执行如下两条命令进行测试:

nslookup qqqq.dns.bypass.world
ping -c 1 asdf.dns.bypass.world

可以看到DNS Server日志如下:

./coredns -conf conf/coredns.conf
dns.bypass.world.:53
2018/03/21 16:40:03 [INFO] CoreDNS-1.1.0
2018/03/21 16:40:03 [INFO] linux/amd64, go1.9.2, 93ade7c-dirty
CoreDNS-1.1.0
linux/amd64, go1.9.2, 93ade7c-dirty
Source Ip: 58.22.*.* Address: qqqq.dns.bypass.world. Time: 2018-03-21 16:40:16.401635432 +0800 CST m=+13.074043412
Source Ip: 58.22.*.* Address: asdf.dns.bypass.world. Time: 2018-03-21 16:40:31.946179174 +0800 CST m=+28.618587169

用mongodb客户端查看数据库信息,如下:

mongo --port 27018
MongoDB shell version: 2.6.10
connecting to: 127.0.0.1:27018/test
> use coredns
switched to db coredns
> db.Qrecoders.find().pretty()
{
 "_id" : ObjectId("5ab208bfb21405522b18634a"),
 "qip" : "58.22.*.*",
 "qaddress" : "qqqq.dns.bypass.world.",
 "qtime" : ISODate("2018-03-21T16:40:16.816Z")
}
{
 "_id" : ObjectId("5ab208c2b21405522b18634b"),
 "qip" : "58.22.*.*",
 "qaddress" : "asdf.dns.bypass.world.",
 "qtime" : ISODate("2018-03-21T16:40:31.062Z")
}
Type "it" for more

0x05 后续

到此上篇文章留下的几个坑算是完美的填上。只需要写个简单的Django,把MongoBDB数据库查询api开放出来,整个环境算是组建完成。在写这篇文章之前,看到原来ceye.io 后端dns server 调用的是twisted组件,twisted 由python编写,经过测试发现twisted在这种场景下不如coredns更有优势,于是放弃熟悉的Python转学一段时间Golang,才算是读懂了coredns代码,并修改插件,填上了上篇文章留下的坑。

点赞

发表评论