探索云主机商家和测评

利用PowerDNS GeoIP版自建多节点,分区解析自用DNS服务

不管是不是前一段时间CloudXNS事件,还是我们项目需要,应该还是有不少的用户会选择自建DNS。不过对于我们大部分用户而言也没有必要自建DNS,因为我们网站项目大部分都是符合规定的,即便用第三方免费DNS要求我们进行资料提交也没有多大问题,毕竟我们需要用他们的产品和服务。

从网上提供的信息来看,自建DNS使用较多的还是PowerDNS软件,如果我们有时间或者希望学习自建DNS,可以尝试安装试试。这篇文章来自Senra同学关于利用PowerDNS GeoIP版自建多节点,分区解析自用DNS服务整理文章,这里经过整理分享出来。

第一、PowerDNS安装

由于Centos6平台求稳,所以各种包的版本都比较落后,因此在PowerDNS的官方源中没有支持GeoIP的版本,这特么就很尴尬了,在Github发issue求助被告知因为yaml-cpp版本不够所以只能自己编译后,我就开始了长达两天的折腾。

其实吧,一开始没发现官方的Github里有打包脚本,于是只能自己拆Centos6和Centos7的src.rpm包来拼一份spec出来,在折腾半天后发现各种不对劲,于是重新去找,结果在官方的Github里发现了build-scripts/build-auth-rpm这个脚本……,好吧,拿来修修改改,加个pdns-backend-geoip进去,然后开始了编译打包。接着就碰到了一个问题,成功编译,成功打包,成功安装,然后……查询不出设置的txt记录,提示如下

Exception building answer packet for xx.ip.example.com (All data was not consumed) sending out servfail

这就很绝望,因为查询a记录啥都正常,于是怀疑是不是编译过程中有啥依赖有问题,折腾了一天,最后发现……yaml格式的配置文件中txt记录部分少了俩空格……这,我的内心是崩溃的,大哥,你格式不对提醒下啊,别报这种八竿子打不到一起的错误啊。好吧,总算是成功了,所以用Centos6的各位就不用蛋疼了,用我的rpm包就行。

至于Centos7以及其他系统的各位,请参照官方文档从官方repo或者系统自带的仓库安装。Centos6请参照如下,第一个yaml-cpp也是我编译的最新版本,官方的太老了,不支持,另外还会安装GeoIP这个包,请确保添加了epel或者city-fan源

yum install http://down.senra.me/Senra-Build/yaml-cpp/yaml-cpp-0.5.3-1.el6.x86_64.rpm http://down.senra.me/Senra-Build/pdns/pdns-4.1.0-rc1.el6.x86_64.rpm http://down.senra.me/Senra-Build/pdns/pdns-backend-geoip-4.1.0-rc1.el6.x86_64.rpm http://down.senra.me/Senra-Build/pdns/pdns-tools-4.1.0-rc1.el6.x86_64.rpm

之后就可以开始配置了(默认没有开机启动,请使用chkconfig pdns on来设置)。

第二、PowerDNS配置

配置的话主要有三个,pdns配置、zone配置、dnssec配置(可选)

1、pdns.conf 这个默认在/etc/pdns/pdns.conf 中,可能其他系统有所不同,找不到请使用如下命令

find / -name "pdns.conf*"

当然也可能找到pdns.conf-dist这个文件,这是默认配置样本,因为是GeoIP版本,所以大部分配置其实都没用,可以按照我的修改下。

cat >/etc/pdns/pdns.conf<<'EOF'
logging-facility=0
resolver=8.8.4.4:53
expand-alias=yes
launch=geoip
setgid=pdns
setuid=pdns
geoip-database-files=/data/pdns/geoip/GeoIP.dat /data/pdns/geoip/GeoIPv6.dat /data/pdns/geoip/GeoIPCity.dat /data/pdns/geoip/GeoLiteCityv6.dat /data/pdns/geoip/GeoIPISP.dat /data/pdns/geoip/GeoIPOrg.dat /data/pdns/geoip/GeoLiteASNum.dat /data/pdns/geoip/GeoIPASNumv6.dat
geoip-database-cache=memory
geoip-zones-file=/data/pdns/zone.yaml
geoip-dnssec-keydir=/data/pdns/key
EOF

其中如下两行,是使用alias(也叫aname)记录的前提条件。

resolver=8.8.4.4:53
expand-alias=yes

这个记录和CloudXNS的Link记录以及CloudFlare的CNAME Flattening记录一样都是为了解决主域名无法CNAME而生的,确实是挺好用的。另外第一行是为了将pdns的日志分离开,如果和你其他软件的日志的冲突,也可以改成其他数字(0-7),这个需要配合如下命令。

echo -n "local0.* -/var/log/pdns.log" >/etc/rsyslog.d/pdns.conf
service rsyslog restart

另外,请修改geoip-database-files,我这边的不是默认路径,而且额外加入了Maxmind的付费库以便提高精准度,默认路径在/usr/share/GeoIP文件夹,当然我还是建议做软连接到和zone.yaml以及key一个文件夹,方便下面的同步(如果默认GeoIP文件夹空的话,请运行geoipupdate命令更新)

下面添加一个zone.yaml方便参考使用:

mkdir -p /data/pdns/key /data/pdns/geoip

cat >/data/pdns/zone.yaml<<'EOF'
domains:
- domain: example.com
ttl: 3600
records:

example.com:
- soa:
content: ns.example.net hostmaster.example.net 20171005 7200 3600 86400 1800
ttl: 3600
- ns:
content: ns1.example.net
ttl: 86400
- ns:
content: ns2.example.net
ttl: 86400
- a:
content: 127.0.0.1
ttl: 600
- txt:
content: "senra dns works"
ttl: 600

"*.ip.example.com":
- txt:
content: "IP%af: %ip, Continent: %cn, Country: %co, ASn: %as, Region: %re, Organisation: %na, City: %ci"
ttl: 0

kor.as.geo.example.com:
- a: 37.252.244.19
jpn.as.geo.example.com:
- a: 37.252.228.11
chn.as.geo.example.com:
- a: 103.243.255.114
hkg.as.geo.example.com:
- a: 37.252.249.20
twn.as.geo.example.com:
- a: 37.252.243.19
sgp.as.geo.example.com:
- a: 217.146.9.10
tha.as.geo.example.com:
- a: 217.146.0.10
vnm.as.geo.example.com:
- a: 203.162.172.10
ind.as.geo.example.com:
- a: 217.146.11.10
rus.eu.geo.example.com:
- a: 37.252.254.10
gbr.eu.geo.example.com:
- a: 37.252.230.11
fra.eu.geo.example.com:
- a: 37.252.225.11
deu.eu.geo.example.com:
- a: 37.252.248.36
nld.eu.geo.example.com:
- a: 188.172.219.26
usa.na.geo.example.com:
- a: 162.220.221.10
can.na.geo.example.com:
- a: 188.172.212.10
bra.sa.geo.example.com:
- a: 37.252.238.11
aus.oc.geo.example.com:
- a: 37.252.240.19
zaf.af.geo.example.com:
- a: 188.172.217.60

unknown.af.geo.example.com:
- a: 188.172.217.60
unknown.as.geo.example.com:
- a: 37.252.228.11
unknown.eu.geo.example.com:
- a: 178.255.152.99
unknown.na.geo.example.com:
- a: 162.220.221.10
unknown.oc.geo.example.com:
- a: 37.252.240.19
unknown.sa.geo.example.com:
- a: 37.252.238.11
unknown.unknown.geo.example.com:
- a: 37.252.249.20

services:
www.example.com: [ '%co.%cn.geo.example.com', 'unknown.%cn.geo.example.com', 'unknown.unknown.geo.example.com' ]

EOF

yaml的写法我个人还是不太熟的,所以如果你熟的话请尽管浪,我这边的IP用的是某机房全球各地的IP,地区多,拿来测试效果极好,配置完成后请启动PowerDNS (还是得把下面的dnssec配置好,起码创建好,不然缺文件不好启动),另外请务必参照yaml写法,不然别想跑起来,可以使用某个js-yaml的网页来校对是否写错。

service pdns restart

至于DNSSEC,直接创建一下:

pdnsutil secure-zone example.com
pdnsutil show-zone example.com

然后把返回结果填到你的域名商的DNSSEC设置那儿就行,挑着填,不用都写,建议sha256那个就够了。

第三、PowerDNS同步设置

要知道,为了保证速度以及可靠性,我们至少有两个NS节点,这也是一个域名NS的最少要求。所以,多个节点同步就是一个问题了,由于PowerDNS的GeoIP版本不存在Master以及Slave的区分,所以我们需要额外的方法来实现同步。我推荐btsync (也叫sync home或者resilio sync) 或者 syncthing 以及rsync。

我之前打折的时候买了俩btsync的key,所以这儿就用它了,安装我博客有文章,我这边不说其他的,直接写命令了 ——>传送门

rpm --import https://linux-packages.resilio.com/resilio-sync/key.asc
cat >/etc/yum.repos.d/resilio-sync.repo<<'EOF'
[resilio-sync] name=Resilio Sync
baseurl=https://linux-packages.resilio.com/resilio-sync/rpm/$basearch
enabled=1
gpgcheck=1
EOF

yum install resilio-sync -y
sed -i 's/127.0.0.1/0.0.0.0/g' /etc/resilio-sync/config.json
service resilio-sync restart
chkconfig --add resilio-sync

然后你访问http://IP:8888/ 就能看到web界面了,简单设置密码以及节点名字啥的,然后在你本机上以及其他节点上都装好,添加一个文件夹,我这边路径就是/data/pdns了,(其实,你也可以在自己电脑上装一个,这样你直接本地修改就能静默同步到节点上,很是方便)

各个节点设置完成,尝试修改文件,确认是否会自动同步。

最后一个问题,由于PowerDNS不能自动检测zone文件变动,所以需要手动重载,如果你使用rsync的话有post script这个设置,可以在同步后执行如下命令实现重载配置

pdns_control reload

如果你用syncthing,可以使用它的api功能写个agent监听同步事件,但是btsync的api我本以为是直接用的,后来发现还额外收费,贵的可怕,放弃,换个思路。使用inotify来直接对文件的事件监听然后触发操作,试了下发现效果意外的不错。

echo "nohup zone_watcher 2>&1 >>/tmp/watcher.log &" >>/etc/rc.local
cat >/usr/bin/zone_watcher<<'EOF'
#!/bin/sh
cleanlog=`echo -n "" > /tmp/pdns-zone.log`
zonefile="/data/pdns/zone.yaml"
while inotifywait -q -e modify,move_self $zonefile >/dev/null; do
echo -e "`date "+%Y-%m-%d %H:%M:%S"` Zone Changed, Reload: [ `sleep 2 & pdns_control reload || echo -n "Failed"` ]" >>/tmp/pdns-zone.log
done
EOF

chmod +x /usr/bin/zone_watcher
nohup zone_watcher 2>&1 >>/tmp/watcher.log &

然后就能在后台监视了,发现修改后会延迟2秒然后重载。

到这儿一切都OK了,我这测试效果还行,虽然部分区域分配的ip还是有些问题,不过也已经基本够用了。

自建DNS主要是灵活性够高,当然如果不想折腾还是建议选择现成的,毕竟自建一是维护麻烦,二是如果想要效果好成本也是挺大的,特别是DNS建议使用anycast的节点来确保在线率以及查询速度。

投上你的一票
转载保留:老部落 » 利用PowerDNS GeoIP版自建多节点,分区解析自用DNS服务