兽兽在v2有提到在 stretch 中配置 gdnsd 顺便还写了文出来。刚好也遇到了 CloudXNS 事件,这边就介绍一下在 CentOS 里装 gdnsd 的指导吧~

gdnsd 还是很有特色的,因为它有个插件系统,功能还是挺强大的,因为实现了自带的状态监控 ( http 以及 tcp ),并且能够通过多个插件配合实现宕机切换,很有意思,还能通过外部命令来进行自定义的检测。

此外,和 PowerDNS 不同的是这个由于使用了 libmaxminddb 库,支持 GeoIP2 格式数据库。

介绍

其实这里开始往下的内容都是照搬书生的……然而只发个 CentOS 6.x rpm 的链接应该没什么的吧(

Gdnsd on Github

首先是启动脚本,建议存一份:

View Script on Github

然后是 CentOS 6.x 的 RPM 包,书生编译的。建议添加 RPMForge 源以及 EPEL 源。

1
2
3
4
yum install http://down.senra.me/Senra-Build/colm/colm-0.13.0.4-2.el6.x86_64.rpm -y
yum install http://down.senra.me/Senra-Build/ragel/ragel-6.10-1.el6.x86_64.rpm -y
yum install http://down.senra.me/Senra-Build/libmaxminddb/libmaxminddb-1.2.0-4.el6.x86_64.rpm -y
yum install http://down.senra.me/Senra-Build/gdnsd/gdnsd-2.2.4-1.el6.x86_64.rpm -y

配置

建议看下官方的 Wiki:

Gdnsd Wiki on Github

以及兽兽的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
cat >/etc/gdnsd/config<<'EOF' options => {
listen => any ;监听所有interface,如果指定ip的话可以带上端口
dns_port => 53 ;对于没有指定端口的ip就监听53端口
chaos_response => "SenraDNS" ;返回信息
}
service_types => {
example_monitor => { ;一个http检测插件
plugin => http_status
ok_codes => [200, 301, 302, 403, 404] ;认为这些返回码代表网站正常,可以自己选择
vhost => example.org ;指定检测时使用的Host,因为只能检测ip,不带上Host会串网站
url_path => / ;检测的url路径
}
}
plugins => {
geoip => { ;geoip插件
maps => {
china_map => {
geoip_db => GeoLiteCity.dat ;指定数据库
datacenters => [default-dc, cn-dc] ;类似meta插件指定的地址标签,按照官方说明geoip几乎包括了meta插件的全部代码,是它的超集,所以搞不懂可以去看看meta插件说明
map => {
AS => {CN => [cn-dc, default-dc]} ;指定大陆为AS(亚洲),国家为CN(中国)的返回cn-dc对应记录,不然就返回后一个default-dc,有多个大陆或者国家会全部匹配过去
}
}
}
resources => {
example_org => {
map => china_map ;使用的map映射
service_types => example_monitor ;使用的检测服务
dcmap => {
cn-dc => {
addrs_v4 => 192.0.2.4
addrs_v6 => 2001:DB8::4
},
default-dc => {
addrs_v4 => 192.0.2.5
addrs_v6 => 2001:DB8::5
},
}
}
}
}
}
EOF
cat >/etc/gdnsd/zones/example.com<<'EOF'
$TTL 86400
@ IN SOA ns1.example.com. hostmaster.example.com. (
1 ; serial
7200 ; refresh
900 ; retry
1209600 ; expire
10800 ; ncache
)
@ NS ns1.example.com.
@ NS ns2.example.com.
ns1 A 192.0.2.2
ns2 A 192.0.2.3
ns1 AAAA 2001:DB8::2
ns2 AAAA 2001:DB8::3
EOF
cat >/etc/gdnsd/zones/example.org<<'EOF'
$TTL 3600
@ IN SOA ns1.example.com. hostmaster.example.com. (
1 ; serial
7200 ; refresh
900 ; retry
1209600 ; expire
10800 ; ncache
)
@ NS ns1.example.com.
@ NS ns2.example.com.
@ DYNA geoip!example_org ;使用配置中的geoip插件来实现动态A(DYA)记录
www CNAME example.org.
EOF
mkdir /etc/gdnsd/geoip
cd /etc/gdnsd/geoip
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz && gzip -df GeoLiteCity.dat.gz
#检测配置是否正确
service gdnsd checkconf
#检测gdnsd状态
service gdnsd status

一些插件

记录类

  • GdnsdPluginSimplefo
    用于切换主备记录,可配合状态检测实现宕机切换,仅支持 A(AAAA) 记录
  • GdnsdPluginMultifo
    类似上面的,但是这是多IP轮询状态下切换IP组,仅支持 A(AAAA) 记录
  • GdnsdPluginWeighted
    带权重的负载均衡式,支持 A(AAAA) 记录以及 CNAME 记录
  • GdnsdPluginMetafo
    这个是给记录或者记录组加标签,然后可以在其他插件中调用,支持 A(AAAA) 记录以及 CNAME 记录
  • GdnsdPluginGeoip
    使用 MaxMind 的 GeoIP 或者 GeoIP2 格式数据库来进行基于地理位置的负载均衡 GSLB,当然也可以用于实现 GeoDNS (其实一个意思),仅支持 A(AAAA) 记录

检测类

  • GdnsdPluginHttpStatus
    可以通过 http 方式检测网站的状态码,如果在设置的正常状态码列表中即为正常,反之触发宕机切换,可指定端口
  • GdnsdPluginTcpConnect
    类似上面的,但是是通过 TCP 检测端口是否为开放状态,可指定端口
  • GdnsdPluginExtmon
    通过调用 shell 命令来进行检测,判断状态依靠返回码
  • GdnsdPluginExtfile
    通过读取文件中的内容来判断状态,文件内容可以为其他监控生成数据,但是要依据格式

特殊类

  • GdnsdPluginStatic
    直接返回固定的解析结果,支持A(AAAA)记录以及CNAME记录,基本上只用于测试
  • GdnsdPluginReflect
    用于在线调试的插件,可以根据配置返回请求解析的IP以及请求信息中的edns的IP
  • GdnsdPluginNull
    额,这个……真的是 null,IPv4 返回 0.0.0.0,IPv6 返回 :: ,CNAME 返回 invalid ,实际作用不明

同步

关于同步,当然是建议 rsync 去做热同步,不过 btsync 和 syncthing 也是可以的。

同步配置后使用 gdnsd reload-zones 来重载配置文件

如果你的内核版本够高,比如是4.x的那么gdnsd有内置的inotify,会自动检测配置文件改动。

如果是自带的2.63内核,那么请参照书生的 PowerDNS 文章丢个 zone_watcher 脚本上去,改改zone文件位置就行。加上-r参数是递归检测文件夹内文件:

1
2
3
4
5
6
7
8
9
10
11
12
echo "nohup zone_watcher 2>&1 >>/tmp/watcher.log &" >>/etc/rc.local
cat >/usr/bin/zone_watcher<<'EOF'
#!/bin/sh
cleanlog=`echo -n "" > /tmp/gdnsd-zone.log`
zonefile="/etc/gdnsd"
while inotifywait -qr -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 &