本文章为各位介绍Bind基于DLZ实现智能DNS配置教程,如果有需要对于这个智能dns配置的朋友可以进来参考此教程.
简介:在我看来基于Bind的只能DNS方案主要包括两个部分:Geolocation和Dynamic Record。国内的业界对智能DNS的定位也无非这两点,但是我所理解的智能DNS是建立在这两条基础上的智能调度系统,比如我有三个负载能力不同的数据中心,DNS可以根据数据中心的metrics(这里可能包括带宽,服务能力等)实现流量的调度,限于个人水平个人未在这个方向有所实践,这个话题留作以后讨论,所以本文只针对前两个问题。由于Bind本身的配置可运维性比较差,这就引出本文主要讨论的DLZ。
原理:DLZ实际上就是扩展了Bind,将Zonefle的内容放到外部数据库里,然后给Bind配置查询语句从数据库里查询记录。当修改数据库里的记录信息的时候,无需重启Bind,下次客户请求时直接就能返回新的记录了。另外,DLZ本身不支持缓存,所以需要自己根据实际情况解决查询的问题。
安装:
注意:这里我以CentOS7上安装dlz-mysql模块为例。
安装依赖:yum install mariadb-devel gcc wget patch make
下载源码:
Bind9.8之前的版本需要打patch,具体可参考DLZ官方文档,Bind9.8之后(包括9.8)的版本已经集成DLZ:
- wgetftp://ftp.isc.org/isc/bind9/9.10.1/bind-9.10.1.tar.gz
- tarxzfbind-9.10.1.tar.gz
- cdbind-9.10.1
配置:由于CentOS7目录结构上的变更,在编译dlz-mysql时会找不到库文件或者head文件,所以要做个软连接:
- ln-s/usr/lib/mysql/usr/lib64/mysql
- ./configure--prefix/opt/bind--with-dlz-filesystem--with-dlz-mysql
编译:make
安装:make install
模型:
注意:DLZ没有限制用户的数据模型,你可以根据业务逻辑定义模型,然后构造自己的查询语句即可,官方给出了建议的模型.
建模:
- FieldTypeNullKeyDefaultExtra
- zonetextYESNULL
- hosttextYESNULL
- typetextYESNULL
- datatext
- ttlint(11)YESNULL
- mx_prioritytextYESNULL
- refreshint(11)YESNULL
- retryint(11)YESNULL
- expireint(11)YESNULL
- minimumint(11)YESNULL
- serialbigint(20)YESNULL
- resp_persontextYESNULL
- primary_nstextYESNULL
- zone区域
- host记录名
- type记录类型
- data记录值
- ttl缓存时间
- mx_prioritymx记录优先级
- refreshSOA记录的刷新时间
- retrySOA记录的重试时间
- expireSOA记录的过期时间
- minimumSOA记录的minimum
- serialSOA记录的序列号
- resp_personSOA记录的序列号
- primary_ns<尚不明确这个字段的意义>
建库建表,新建数据库:
create database demo;
新建record表:
- CREATETABLEIFNOTEXISTSrecords(
- idint(10)unsignedNOTNULLAUTO_INCREMENT,
- zonevarchar(255)NOTNULL,
- hostvarchar(255)NOTNULL,
- typeenum('A','MX','CNAME','NS','SOA','PTR','TXT','AAAA','SVR','URL')NOTNULL,
- datavarchar(255)NOTNULL,
- ttlint(11)NOTNULL,
- mx_priorityint(11)DEFAULTNULL,
- refreshint(11)DEFAULTNULL,
- retryint(11)DEFAULTNULL,
- expireint(11)DEFAULTNULL,
- minimumint(11)DEFAULTNULL,
- serialbigint(20)DEFAULTNULL,
- resp_personvarchar(64)DEFAULTNULL,
- primary_nsvarchar(64)DEFAULTNULL,
- PRIMARYKEY(id),--phpfensi.com
- KEYtype(type),
- KEYhost(host),
- KEYzone(zone)
- )ENGINE=MyISAMDEFAULTCHARSET=utf8AUTO_INCREMENT=1;
新建acl表:
- CREATETABLEIFNOTEXISTSacl(
- idint(10)unsignedNOTNULLAUTO_INCREMENT,
- zonevarchar(255)NOTNULL,
- clientvarchar(255)NOTNULL,
- PRIMARYKEY(id),
- KEYclient(client),
- KEYzone(zone)
- )ENGINE=MyISAMDEFAULTCHARSET=utf8AUTO_INCREMENT=1;
配置:GeoIP
这块目前还没有那么灵活,基本上都是基于acl来实现的,虽然最新版的bind 9.10支持maxmind的api来做Geo,但还是改写配置文件的方式,下面是一个示例:
- acl"US"{
- 3.0.0.0/8;
- 4.0.0.0/25;
- 4.0.0.128/26;
- 4.0.0.192/28;
- 4.0.0.208/29;
- 4.0.0.216/30;
- 4.0.0.220/31;
- };
- view"north_america"{
- match-clients{US;CA;MX;};
- recursionno;
- zone"foos.com"{
- typemaster;
- file"pri/foos-north-america.db";
- };
- };
- view"other"{
- match-clients{any;};
- recursionno;
- zone"foos.com"{
- typemaster;
- file"pri/foos-other.db";
- };
- };
该示例引用自这里,但是我们可以通过DLZ实现GeoIP,二次开发一个自己的driver,然后在driver里根据client ip,结合自己的业务系统实现真正的Geo以及智能业务调度.
Dynamic Record
DLZ新定义了一个配置关键字dlz,完整的配置项参考官方文档,这里给出简要说明:
- dlz"Mysqlzone"{//定义DLZ标识
- database"mysql//database为dlz这个block唯一可指定的关键字,mysql表示使用mysqldriver
- {host=localhostdbname=dns_datassl=tRue}//连接数据库的信息
- {selectzonefromdns_recordswherezone='$zone$'}//用于findzone调用,查询zone
- {selectttl,type,mx_priority,casewhenlower(type)='txt'thenconcat('\"',data,'\"')
- elsedataendfromdns_recordswherezone='$zone$'andhost='$record$'
- andnot(type='SOA'ortype='NS')}//用于lookup调用,查询record
- {selectttl,type,mx_priority,data,resp_person,serial,refresh,retry,expire,minimum
- fromdns_recordswherezone='$zone$'and(type='SOA'ortype='NS')}//用于authority调用,查询SOA或者NS记录,注意这个配置是可选的,SOA和NS查询可以放到lookup调用里,具体见后文
- {selectttl,type,host,mx_priority,data,resp_person,serial,refresh,retry,expire,
- minimumfromdns_recordswherezone='$zone$'andnot(type='SOA'ortype='NS')}//用于allnode调用,和接下来的allowzonexfr一起来提供AXFR查询,可选的配置项
- {selectzonefromxfr_tablewherezone='$zone$'andclient='$client$'}//用于allowzonexfr()调用,用于查询客户端是否可发起AXFR查询,可选的配置项
- {updatedata_countsetcount=count+1wherezone='$zone$'}";
- };
注意:此配置为最新Bind版本的配置,如果是打patch的版本请将$换成%,以下的配置同样,这里也给出我的配置:
- logging{
- channelall{
- file"/opt/bind/log/named.log"versions1;
- print-timeyes;
- severitydynamic;
- print-categoryyes;
- print-severityyes;
- };
- categorydefault{all;};
- categoryqueries{all;};
- };
- options{
- directory"/opt/bind/var/";
- listen-on-v6{none;};
- listen-on{any;};
- pid-file"/var/run/named.pid";
- recursionyes;
- allow-transfer{127.0.0.1;};
- };
- dlz"mysql-dlz"{
- database"mysql
- {host=localhostdbname=demossl=falseport=3306user=rootpass=thinkin}
- {selectzonefromrecordswherezone='$zone$'limit1}
- {selectttl,type,mx_priority,casewhenlower(type)='txt'thenconcat('\"',data,'\"')whenlower(type)='soa'thenconcat_ws('',data,resp_person,serial,refresh,retry,expire,minimum)elsedataendfromrecordswherezone='$zone$'andhost='$record$'}
- {}
- {selectttl,type,host,mx_priority,datafromrecordswherezone='$zone$'andnot(type='SOA'ortype='NS')}
- {selectzonefromaclwherezone='$zone$'andclient='$client$'}";
- };
- zone"."IN{
- typehint;
- file"named.root";
- };
- key"rndc-key"{
- algorithmhmac-md5;
- secret"OdEg+tCn/bMe+/2vbJgQvQ==";
- };
- controls{
- inet127.0.0.1allow{localhost;}keys{"rndc-key";};
- };
注意:这里的配置开启了递归解析且支持本机发起的AXFR请求。
根zonefile
wget -SO /opt/bind/var/named.root http://www.internic.net/domain/named.root
启动:/opt/bind/sbin/named -n1 -c /opt/bind/etc/named.conf -d9 -g
测试,导入数据,导入records数据:
- INSERTINTOdemo.records(zone,host,type,data,ttl)VALUES(phpfensi.com','www','A','1.1.1.1','60');
- INSERTINTOdemo.records(zone,host,type,data,ttl)VALUES('phpfensi.com','cloud','A','2.2.2.2','60');
- INSERTINTOdemo.records(zone,host,type,data,ttl)VALUES('phpfensi.com','ns','A','3.3.3.3','60');
- INSERTINTOdemo.records(zone,host,type,data,ttl)VALUES('phpfensi.com','blog','CNAME','cloud.phpfensi.com.','60');
- INSERTINTOdemo.records(zone,host,type,data,ttl)VALUES('phpfensi.com','@','NS','ns.phpfensi.com.','60');
- INSERTINTOdemo.records(zone,host,type,ttl,data,refresh,retry,expire,minimum,serial,resp_person)VALUES('phpfensi.com','@','SOA','60','ns','28800','14400','86400','86400','2012020809','admin');
导入acl数据:
INSERT INTO demo.acl (zone, client) VALUES ('phpfensi.com', '127.0.0.1');
测试记录:
- dig@127.0.0.1www.phpfensi.com a
- dig@127.0.0.1blog.phpfensi.com a
- dig@127.0.0.1blog.phpfensi.com cname
- dig@127.0.0.1phpfensi.com ns
- dig@127.0.0.1www.phpfensi.com axfr