BIND DLZ PostgreSQL

智能DNS工作原理:
在用户解析一个域名的时候,判断一下用户的IP,然后跟DNS服务器内部的IP表匹配一下,看看用户是电信还是网通用户,然后给用户返回对应的IP地址。目前的域名服务运营商不提供智能DNS服务,所以必须自行架设DNS服务或者使用网上免费的智能DNS服务,如DNSPOD

本实例中我架设的是一个简单的内外解析模式,如果需要增加其他类别(电信、网通)只需添加对于的 view 即可。

bind 在很早以前就已经集成了bind-dlz 数据库模块,可支持sqllit、bdb Mysql  PostgreSQL ODBC LDAP等数据源,详见:http://bind-dlz.sourceforge.net/

本次架设采用PostgreSQL作为数据源实现,数据库已经准备完毕(可使用已有的数据库系统,创建一个新库即可)。

1、配置说明
两个view
       local   内部网络
       any     其他(公网)

两台DNS服务器
       master dns 10.0.0.8    222.222.222.8
       slave  dns  10.0.0.9     222.222.222.9

2、创建数据库、表并添加基本记录记录

create database dns_dlz;  
create table dns_records(  
    zone character varying(256),  
    host character varying(256) NOT NULL default '@',     
    ttl integer,  
    view character varying(256),  
    type  character varying(256),  
    mx_priority integer,  
    data character varying(256),  
    resp_person character varying(256),  
    serial integer,  
    refresh integer,  
    retry  integer,  
    expire   integer,  
    minimum integer  
);  
  
create INDEX dns_records_host_index on dns_records (host);  
create INDEX dns_records_type_index on dns_records ("type");    
create INDEX dns_records_zone_index on dns_records ("zone");   
# zone sample.com
#soa 记录  
insert into dns_records(zone, host, ttl, view, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum) values ('sample.com', '@', 600, 'LOCAL', 'SOA', NULL, 'sample.com.', 'root.sample.com.', 2011083001, 28800, 14400, 86400, 86400);  
insert into dns_records(zone, host, ttl, view, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum) values ('sample.com', '@', 600, 'ANY', 'SOA', NULL, 'sample.com.', 'root.sample.com.', 2011083001, 28800, 14400, 86400, 86400);  
#dns 记录  
insert into dns_records(zone, host, ttl, view, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum) values ('sample.com', '@', 600, 'LOCAL', 'NS', NULL, 'ns1.sample.com.', NULL, 2011083001, 28800, 14400, 86400, 86400);  
insert into dns_records(zone, host, ttl, view, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum) values ('sample.com', '@', 600, 'ANY', 'NS', NULL, 'ns1.sample.com.', NULL, 2011083001, 28800, 14400, 86400, 86400);  
#A记录 time.sample.com  
insert into dns_records(zone, host, ttl, view, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum) values ('sample.com', 'time', 600, 'LOCAL', 'A', NULL, '10.0.0.8', NULL, 2011083001, 28800, 14400, 86400, 86400);  
insert into dns_records(zone, host, ttl, view, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum) values ('sample.com', 'time', 600, 'ANY', 'A', NULL, '222.222.222.8', NULL,  2011083001, 28800, 14400, 86400, 86400);  
#A记录 ns1.sample.com  
insert into dns_records(zone, host, ttl, view, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum) values ('sample.com', 'ns1', 600, 'LOCAL', 'A', NULL, '10.0.0.10',  NULL, NULL, NULL, NULL, NULL, NULL);  
insert into dns_records(zone, host, ttl, view, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum) values ('sample.com', 'ns1', 600, 'ANY', 'A', NULL, '222.222.222.10', NULL,  NULL, NULL, NULL, NULL, NULL);  
#mx记录   
insert into dns_records(zone, host, ttl, view, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum) values ('sample.com', '@', 600, 'LOCAL', 'MX', 10, 'mail.sample.com.', NULL, NULL, NULL, NULL, NULL, NULL);  
insert into dns_records(zone, host, ttl, view, type, mx_priority, data, resp_person, serial, refresh, retry, expire, minimum) values ('sample.com', '@', 600, 'ANY', 'MX', 10, 'mail.sample.com.', NULL,  NULL, NULL, NULL, NULL, NULL);  
其他域名的添加方式类似,将zone项替换为对于的域名即可


3、bind 编译安装及配置

rpm包默认不支持dlz模式,需要使用源码编译

./configure --with-dlz-postgres --enable-threads  --prefix=/usr/local/bind  
./configure --with-dlz-postgres  --build=x86_64-RedHat-linux-gnu --host=x86_64-redhat-linux-gnu --target=x86_64-redhat-linux-gnu --program-prefix= --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include --libdir=/usr/lib64 --libexecdir=/usr/libexec --sharedstatedir=/usr/com --mandir=/usr/share/man --infodir=/usr/share/info --with-libtool --localstatedir=/var --enable-threads --enable-ipv6 --with-pic --disable-openssl-version-check   
以下安装路径为系统默认路径 

配置文件 /etc/named.conf  

其他配置文件路径 /etc/named/

4、创建相关配置文件

cd /etc  
rndc-confgen >rndc.conf  
tail -n6 rndc.conf | head -n5 | sed -e s/#\//g >named.conf  
rm -f rndc.conf  (该文件与 rndc.key 文件一起出现会出现 rndc警告,删除为妙)  
dig > named/named.root  
查看是否存在 /etc/rndc.key 文件,如果没有就生成一个
rndc-confgen -a -c rndc.key

默认的rndc.key 文件中的key名称 好像是 rndckey

手动生成的key名称是 rndc-key

key的名称一定要一致,否则会出现不能使用 rndc 刷新、不能同步的问题。

使用 dnssec-keygen 生成view TSIG key
dnssec-keygen -a hmac-md5 -b 128 -n HOST local  
dnssec-keygen -a hmac-md5 -b 128 -n HOST any  
将生成的key 填入named.conf 对应的位置 
如: 

key "any" {  
        algorithm hmac-md5;  
        secret "0bUZSQ1p3OMbX/6nGB6YPQ==";  
};  
详细见下面的完整配置文件,该配置文件包含文件存储和数据库两种方式(数据库存储已经注视掉),文件存储方式已经包含master slave 之间的TSIG 方式同步。

及在不同的view中使用各自key进行同步。

完整 named.conf 内容

options  
{  
        directory       "/var/named";  
        dump-file       "data/cache_dump.db";  
        statistics-file "data/named_stats.log";  
        memstatistics-file "data/named_mem_stats.log";  
        #listen-on port 53 { 127.0.0.1; 10.0.0.8; 222.222.222.8; };  
        allow-recursion { 127.0.0.1; };  
        allow-transfer  { dns_ip; };     #使用文件存储zone时使用 slave 无需此项  
        also-notify     { 10.0.1.9; };   #使用文件存储zone时使用 slave 无需此项  
  
        edns-udp-size   512;  
};  
include "/etc/rndc.key";  
controls {  
        inet 127.0.0.1 port 953  
                allow { 127.0.0.1; } keys { "rndckey"; };  
};  
key "any" {  
        algorithm hmac-md5;  
        secret "0bUZSQ1p3OMbX/6nGB6YPQ==";  
};  
key "local" {  
        algorithm hmac-md5;  
        secret "OuhPGr+uFmSeOm04ZPJFmA==";  
};  
  
acl "dns_ip" {  
        10.0.0.8; #master  
        10.0.0.9; #slave  
};  
  
  
acl "LOCAL" {  
        10.0.0.0/8;  
};  
  
include "/etc/named/local_acl.conf";  
include "/etc/named/any.conf";  
  
logging {    
        category edns-disabled { null; };  
        channel query_log {    
                file "/var/named/data/query.log"        versions 3 size 20m;    
                severity                info;    
                print-time              yes;    
                print-category  yes;    
        };    
        category queries {    
                query_log;    
        };  
};
local_acl.conf

#local network view  
view "local" {  
 match-clients         { key local; LOCAL; }; #使用文件存储zone使用,用于master slave同步  
 #match-clients        { LOCAL; };            #使用数据库时的配置,无需同步  
 allow-query-cache     { LOCAL; };  
 allow-transfer        { key local; };        #使用文件存储zone使用,用于master slave同步  
 server 10.0.0.9       { keys { local; }; };  #使用文件存储zone使用,用于master slave同步  
  
 #允许内部ip地址递归查询  
 allow-recursion {  
    10.0.0.0/16;  
    127.0.0.1;  
 };  
  
#------使用文件存储zone 配置-----------  
 zone "sample.com" {  
    type master;               #slave 配置  type slave;  
    file "/etc/named/sample.com.in.zone"  
    # masters { 10.0.0.8; };   #slave 配置  
 };  
 zone "1.0.10.in-addr.arpa" {  
    type master;               #slave 配置  type slave;  
    file "/etc/named/0.0.10.in-addr.arpa;  
    # masters { 10.0.0.8; };   #slave 配置  
 };  
#------使用文件存储zone 配置-----------  
  
#---dlz postgresql database configure----  
# dlz "postgres zone" {  
#   database "postgres 1  
#   {host=10.0.1.19 port=54320 dbname=dns_dlz user=dns_query}  
#   {select zone from dns_records where zone = '$zone$' limit 1}  
#   {select ttl, type, mx_priority, case when lower(type)='txt' then '\"' || data || '\"'   
#           when lower(type)='soa' then data || ' ' || resp_person || ' ' || serial || ' ' || refresh || ' ' || retry || ' ' || expire || ' ' || minimum   
#           else data end from dns_records where zone = '$zone$' and lower(view)='local' and host = '$record$'}  
#   {}  
#   {select ttl, type, host, mx_priority, case when lower(type)='txt' then '\"' || data || '\"' else data end,  
#     resp_person, serial, refresh, retry, expire, minimum from dns_records where zone = '$zone$'}";   
#  };  
#---dlz postgresql database configure---- };  
};  
any.conf
view "any" {  
  
 match-clients           { key local; ANY; };  #使用文件存储zone使用,用于master slave同步  
#match-clients           { ANY; };             #使用数据库时的配置,无需同步  
 allow-query-cache       { ANY; };  
 allow-transfer          { key any; };         #使用文件存储zone使用,用于master slave同步  
 server 10.0.0.9         { keys { any; }; };   #使用文件存储zone使用,用于master slave同步  
 allow-recursion {  
    127.0.0.1;  
    222.222.222.0/24;  
};  
  
#------使用文件存储zone 配置-----------   
zone "sample.com" {   
    type master;  
    file "/etc/named/sample.com.zone";   
    # masters { 10.0.0.8; };   #slave 配置   
};   
  
zone "222.222.222.in-addr.arpa" {  
    type master;               #slave 配置  type slave;      
    file "/etc/named/222.222.222.in-addr.arpa";      
    # masters { 10.0.0.8; };   #slave 配置   
};  
  
#------使用文件存储zone 配置-----------  
#---dlz postgresql database configure----  
#   dlz "postgres zone" {  
#   database "postgres 1  
#   {host=10.0.1.1 port=5432 dbname=dns_dlz user=dns_query}  
#   {select zone from dns_records where zone = '$zone$' limit 1}  
#   {select ttl, type, mx_priority, case when lower(type)='txt' then '\"' || data || '\"'   
#        when lower(type)='soa' then data || ' ' || resp_person || ' ' || serial || ' ' || refresh || ' ' || retry || ' ' || expire || ' ' || minimum   
#    else data end from dns_records where zone = '$zone$' and lower(view)='any' and host = '$record$'}";   
# };  
#---dlz postgresql database configure----  
};  
以上基本配置已经完成,以上分别使用文件或者数据库存储dns记录的均测试完成

个人建议:在dns记录不多的情况下,使用文件存储的方式可能更为合理一些,毕竟使用数据库又增加了一个故障的可能性。

当使用数据库时,可能会因为插入的记录的问题导致named进程的异常退出,所以应该使用程序来完成记录的添加和修改,尽量避免直接操作数据库。

附:测试命令

rndc reload                  #重新加载全部配置

rndc reload  sample.com  IN  view_name  #重新加载指定的域名下指定的View

rndc status                  #检查服务状态

dig @10.0.0.8 www.sample.com  +noauthority +noadditional | grep -Ev "^(;|$)"     #域名解析测试

 #测试基本dns lookup 及兼容性测试

dig +nodnssec +norec +ignore ns . @L.ROOT-SERVERS.NET  

dig +nodnssec +norec +ignore ns . @L.ROOT-SERVERS.NET

dig +dnssec +norec +ignore ns . @L.ROOT-SERVERS.NET

dig +dnssec +norec +ignore any . @L.ROOT-SERVERS.NET

dig +dnssec +norec +vc any . @L.ROOT-SERVERS.NET

dig +norec +dnssec +ignore dnskey se @A.NS.se



5、配置 named-chroot

配置 named-chroot 使named运行在 chroot模式下,
安装 bind97-chroot rpm包
yum -y install bind97-chroot

该包用来创建 chroot下的目录结构及修改named 启动参数 /etc/sysconfig/named
ROOTDIR=/var/named/chroot #自动添加
OPTIONS="-4"         #该参数指定named工作在IPv4模式,在服务器没有IPv6时最好加上该参数,否则日志里有很多连接到一些IPv6域名服务器的错误信息。

其实这个rpm包就是在 /var/named/chroot 目录下面创建named所需的目录,并修改 /etc/sysconfig/named 加上ROOTDIR启动参数

这个工作应该是可以手工完成的。

使用chroot方式时,/var/named/chroot 目录下的文件自动和 系统中的对应文件和文件夹保持同步

由于我对chroot还不是太了解,其中的原理尚不清楚。

检查chroot方式是否启动的方法:

        检查方法基本上就是查看named进程及其调用文件目录是否已经却换到 /var/named/chroot 下

命令:  lsof -p `pgrep named`



6、配置过程中可能出现的错误:

Aug 30 15:24:15 server135 named[2486]: dns_rdata_fromtext: buffer-0x446c1340:1: near eof: unexpected end of input
Aug 30 15:24:15 server135 named[2486]: dns_sdlz_putrr returned error. Error code was: unexpected end of input


上面的错误就是数据库记录中某些字段的不完整导致的
例如:SOA记录中的 resp_person 字段为空



使用rndc reload 重新加载zone时,出现下面的警告(使用文件存储时)

WARNING: key file (/etc/rndc.key) exists, but using default configuration file (/etc/rndc.conf) rndc: get config key list: not found

解决方法:删除 rndc.conf 文件,在named.conf 中include  ”rndc.key" 文件,并确认key的名称的一致。



日志错误

Sep  1 10:14:38 server135 named[9849]: error (network unreachable) resolving '146.46.208.203.in-addr.arpa/PTR/IN': 2001:dc0:4001:1:0:1836:0:140#53
Sep  1 10:14:38 server135 named[9849]: error (network unreachable) resolving 'dns1.telstra.net/A/IN': 2001:dc0:2001:a:4608::59#53

该错误是因为bind尝试使用IPv6连接导致的错误提示,如果bind服务器没有IPv6地址,在启动参数中禁用IPv6即可。

即在  /etc/sysconfig/named  中加上 OPTIONS="-4" 启动选项。



master log中的错误日志

Aug 31 19:03:58 server135 named[8271]: client 10.0.0.9#39084: view local: zone transfer 'sample.com/IXFR/IN' denied
Aug 31 19:03:58 server135 named[8271]: client 10.0.0.9#43464: view local: zone transfer 'sample.com/AXFR/IN' denied

该问题是在master、slave同步过程中出现的,导致同步失败。

该问题的原因是name.conf 中的定义的key在master slave中不相同,或者key的名称不同,请详细检查,确保使用相同的key名称和值

我的配置就是因为rndc key的名称不同导致的。

http://blog.163.com/digoal@126/blog/static/163877040201110235657127/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值