使用BIND9+MySql搭建一个智能解析DNS

  公司之前就有个所谓的“融合性CND”产品,什么叫CDN可以点这里看下,那什么又叫"融合性CDN",过了一天明白了,就是把第三方成熟的CDN产品给封装成带有自己公司logo的接口。首先瞄准的就是CDN里面技术难度不是很高的“智能DNS解析”这块,通俗来讲,智能DNS解析,就是根据用户的IP信息,返回给用户相应的边缘节点,目的是提升用户体验。举个例子,某门户网站,域名www.xxxx.com,源站在北京(IPV4地址111.111.111.111),然后建有两个用于全网加速的边缘节点,一个在济南(IPV4地址222.222.222.222),一个在大连,这时如果有个济南用户请求域名www.xxxx.com的IP地址,普通DNS会直接返回北京的地址111.111.111.111;智能DNS解析,会根据用户的IP信息,发现这人在济南,所以会返回222.222.222.222给用户,这样离得近,估计用户体验会更好(这里提一下,用户体验好不好,影响因素不限于地理上的距离,运营商是否相同,同时在线访问人数,服务器软硬件都有影响)。
  本文适合给直接使用BIND9的网友勘误,没有多少原理上的说明,就是单纯的罗列搭建的基本步骤。估计错误很多,不排除完全错误,不涉及BIND9的二次开发,没有源码或者结构上的解读。强烈建议大家去看官网提供的BIND9运维手册,跟BIND9-DLZ官网指导

1. 安装BIND9所需的依赖

  首先我们要先下载跟安装BIND9所需要的依赖软件。上图:

[root@ecs-dns bindDp]# ll *gz
-rw-r--r-- 1 root root 83709983 Sep  7 14:28 boost_1_59_0.tar.gz
-rw-r--r-- 1 root root  6897636 Sep  7 14:28 cmake-3.6.0.tar.gz
-rw-r--r-- 1 root root 50509574 Sep  7 14:29 mysql-5.7.16.tar.gz
-rw-r--r-- 1 root root  3131891 Sep  7 14:29 ncurses-6.0.tar.gz
-rw-r--r-- 1 root root 16420458 Sep  7 14:30 perl-5.24.4.tar.gz
-rw-r--r-- 1 root root   607698 Sep  7 14:30 zlib-1.2.11.tar.gz

然后我们按下面的顺序,安装BIND9的依赖。

1.1 在这里下载perl的源代码,这里我下载的是perl-5.24.0.tar.gz版本;
tar zxvf perl-5.24.0.tar.gz
cp configure.gnu configure
./configure -des -Dprefix=/usr/local/perl
make
make test # 在这步结束的时候有一个error,但不影响我们后续的操作,test没有完成100%
make install
1.2 在这里下载zlib源码包,然后安装;
tar zxvf zlib-1.2.11.tar.gz
cd zlib-1.2.11
./configure
make
make install
1.3 在这里下载cmake源码包,cmake为mysql的依赖;
tar zxvf cmake-3.6.0.tar.gz
cd cmake-3.6.0
./bootstrap&&gmake&&make&&make install
# 这里的可能会出现如下的错误
# Error when bootstrapping CMake:
# Cannot find appropriate C++ compiler on this system.
# 使用g++ -v命令发现没安装g++编译器
# -bash: g++: command not found,使用下面的yum命令安装g++编译器
yum install gcc-c++ libstdc++-devel
1.4 在这里下载ncurses源码包;
tar zxvf ncurses-6.0.tar.gz
cd ncurses-6.0
./configure
make&&make install
1.5 在这里下载boost库文件,此为mysql5.7.5以上版本所必须的;
# 将boost_1_59_0.tar.gz解压之后放在/usr/local/boost下,这里我尝试将boost_1_62_0.tar.gz解压,发现编译的时候出现了问题,错误解释为需要59的,通过59解压之后成功编译。
mkdir -p /usr/local/boost
cp boost_1_59_0.tar.gz /usr/local/boost/
tar zxvf boost_1_59_0.tar.gz
1.6 我们在这里下载mysql源码包,我下载的是mysql-5.7.16.tar.gz版本的;
tar zxvf  mysql-5.7.16.tar.gz
cd  mysql-5.7.16
groupadd mysql
# 新增mysql组,mysql需要
useradd -r -g mysql mysql
# 新增mysql组下面的mysql用户
mkdir /usr/local/mysql
mkdir -p /data/mysqldb

cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DDOWNLOAD_BOOST=1 -DWITH_BOOST=/usr/local/boost -DMYSQL_DATADIR=/data/mysqldb -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DMYSQL_TCP_PORT=3306 -DWITH_MYISAM_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITH_BLACKHOLE_STORAGE_ENGINE=1
# 这条执行过程中会出现这种错误 -bash: cmake: command not found,将cmake暂时添加到path中
# export PATH="/home/bindDp/cmake-3.6.0/bin/":"$PATH"
# 使用cmake --version验证下,如果出现 cmake version 3.6.0 就OK了

make&&make install # 如果make出错执行 make clean&&rm CMakeCache.txt
cd /usr/local/mysql/

bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql/ --datadir=/data/mysqldb
# 初始化数据库

cp support-files/mysql.server /etc/init.d/mysqld # 复制mysql服务启动脚本
cp /usr/local/mysql/support-files/my-default.cnf /etc/my.cnf # 复制mysql服务启动配置文件

vi /etc/profile # 加入path路径
export PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH
source /etc/profile # 使修改文件立即生效
chkconfig --level 35 mysqld on # 加入开机自启动

2. 编译并安装BIND9

2.1 在这里下载bind的源代码,这里我下载的是bind-9.11.0.tar.gz版本;

  下载完成之后,进入BIND9的源码文件所在的目录,然后使用如下命令解压,配置,安装:

tar zxvf bind9-v9_11.tar.gz
cd bind9-v9_11
./configure --prefix=/usr/local/bind/ --with-dlz-mysql=/usr/local/mysql --enable-threads --disable-chroot --enable-largefile --enable-epoll --without-python
# 这里可能需要手动安装OpenSSL`yum install openssl openssl-devel`
make
make install

  上述的各个flag解析如下:

--enable-largefile 启用大文件支持
--prefix:(重要)表示bind9的安装目录,防止直接安装在根目录,被黑了之后,系统崩了
--sysconfdir:设置named.conf配置文件放置的目录,默认是"$prefix/etc"
--localstatdir=/var:设置run/named.pid放置的目录,默认是“$prefix/var”
--with-libtool:将BIND的库文件编译为动态共享库文件,这个选项默认是为选择的
--enable-threads:多线程支持(官网解析是需要关闭)这个是个可研究的点,下面详细说
--without-python:不依赖Python工具安装
--disable-ipv6:关闭ipv6支持
--with-dlz-mysql:(重要)这是必须要有的,意思是当编译BIND9时候会编译MySQL驱动

--enable-threads这个标签,很重要:
  官网的解释是:BIND9使用MySQL的驱动有一个额外的限制。MySQL针对C的API使用TLS。因此MySQL要求上层APP的每个线程都要执行一个MySQL的“thread initialization”来创建TLS。在DLZ驱动程序API中,这是不可能安全地做到的。因此BIND9只能单独跑一个MySQL驱动的单线程。为了保证BIND9只跑一个单线程,应该在启动named进程时候加上参数"-n 1"。另外,编译单线程的BIND9还可以通过--enable-threads标签,这个标签只在使用MySQL驱动时候才是必须的,官网强烈建议使用非多线程的方式来使用MySQL驱动。
  安装完了之后,现在我们可以先测试一下BIND9的安装结果:

[root@ecs-dns bind9-v9_11]# /usr/local/bind/sbin/named -v
/usr/local/bind/sbin/named: error while loading shared libraries: libmysqlclient.so.20: cannot open shared object file: No such file or directory
# 结果出现错误,无法装载或打开libmysqlclient.so.20,解决方法是用find命令找到libmysqlclient.so.20然后copy到/usr/lib64/下

[root@ecs-dns bind9-v9_11]# mv /usr/local/mysql/lib/libmysqlclient.so.20 /usr/lib64/
[root@ecs-dns bind9-v9_11]# /usr/local/bind/sbin/named -v
BIND 9.11.35 (Extended Support Version) <id:unset_id>
2.2 接下来我们需要配置named.cnf文件

  step1:先切换到正确的目录

[root@study etc]# pwd
/usr/local/bind/etc
[root@study etc]# ll
total 16
drwxr-xr-x 2 root root   96 Sep 21 16:26 acl
-rw-r--r-- 1 root root 1859 Aug 26 16:24 bind.keys
-rw-r--r-- 1 root root  860 Sep 16 17:32 named.conf
-rw-r--r-- 1 root root  479 Aug 26 16:25 rndc.conf
-rw-r--r-- 1 root root  479 Aug 26 16:26 rndc.key
drwxr-xr-x 2 root root   99 Sep 16 17:34 view:

  step2:生成named.conf配置文件

[root@ecs-dns etc]# cd /usr/local/bind/sbin
[root@ecs-dns sbin]# ./rndc-confgen -r /dev/urandom > /usr/local/bind/etc/rndc.conf
[root@ecs-dns sbin]#
[root@ecs-dns sbin]# cd /usr/local/bind/etc/
[root@ecs-dns etc]# tail -n10 rndc.conf | head -n9 | sed -e s/#\//g>named.conf

  step3:生成根服务器文件

[root@ecs-dns etc]# ../bin/dig > ./named.root

  step4:接下来正式配置named.conf文件

[root@study etc]# cat named.conf
key "rndc-key" {
        algorithm hmac-md5;
        secret "E4ghSPC882WXb50g58HHCA==";
};

controls {
        inet 127.0.0.1 port 953
                allow { 127.0.0.1; } keys { "rndc-key"; };
};
options {
    listen-on port 53 {127.0.0.1; 192.168.137.111;};
    directory "/usr/local/bind/var";
    pid-file "named.pid";
    allow-query{any;};
    forwarders{114.114.114.114;8.8.8.8;};
};

acl "dns-ip-list"{
    192.168.137.111;
};

include "/usr/local/bind/etc/acl/CMCC_CN_Shandong_acl.conf"; //中移-中国-山东ACL
include "/usr/local/bind/etc/acl/CUCC_CN_Shandong_acl.conf"; //电联-中国-山东ACL
include "/usr/local/bind/etc/acl/default_acl.conf";
include "/usr/local/bind/etc/view/CMCC_CN_Shandong_view.conf"; //中移-中国-山东DLZ
include "/usr/local/bind/etc/view/CUCC_CN_Shandong_view.conf"; //中联-中国-山东DLZ
include "/usr/local/bind/etc/view/default_view.conf";

  step5:配置acl文件如下:

[root@study acl]# cat CMCC_CN_Shandong_acl.conf
acl CMCC_CN_Shandong{
    {192.168.136.255; 192.168.137.1;};
};
[root@study acl]# cat CUCC_CN_Shandong_acl.conf
acl CUCC_CN_Shandong{
        192.168.137.2/32;
};
[root@study acl]# cat default_acl.conf
acl default{
    0.0.0.0/0;
};
[root@study acl]#

  step6:配置view文件如下:

[root@study view]# cat CMCC_CN_Shandong_view.conf
view "CMCC_CN_Shandong_view" {
        match-clients {CMCC_CN_Shandong;};
        dlz "Mysql zone" {
                database "mysql
                {host=127.0.0.1 dbname=example ssl=false port=3306 user=root pass=com}
                {select zone from dns_records where zone = '$zone$' and (view = 'CMCC' and country = 'CN' and province = 'Shandong' or view = 'DEFAULT') limit 1}
                {select ttl, type, mx_priority, case when lower(type)='txt' then concat('\"', data, '\"') when lower(type)='soa' then concat_ws(' ', data, resp_person, serial, refresh, retry, expire, minimum) else data end as mydata from dns_records where zone= '$zone$' and host = '$record$' and (view = 'CMCC' and country = 'CN' and province = 'Shandong' or view = 'DEFAULT')}
                {}
                {}
                {}
                {update data_count set count = count + 1 where zone ='$zone$' and (view = 'CMCC' and country = 'CN' and province = 'Shandong' or view = 'DEFAULT')}";
        };
};

[root@study view]# cat CUCC_CN_Shandong_view.conf
view "CUCC_CN_Shandong_view" {
        match-clients {CUCC_CN_Shandong;};
        dlz "Mysql zone" {
                database "mysql
                {host=127.0.0.1 dbname=example ssl=false port=3306 user=root pass=com}
                {select zone from dns_records where zone = '$zone$' and (view = 'CUCC' and country = 'CN' and province = 'Shandong' or view = 'DEFAULT') limit 1}
                {select ttl, type, mx_priority, case when lower(type)='txt' then concat('\"', data, '\"') when lower(type)='soa' then concat_ws(' ', data, resp_person, serial, refresh, retry, expire, minimum) else data end as mydata from dns_records where zone= '$zone$' and host = '$record$' and (view = 'CUCC' and country = 'CN' and province = 'Shandong' or view = 'DEFAULT')}
                {}
                {}
                {}
                {update data_count set count = count + 1 where zone ='$zone$' and (view = 'CUCC' and country = 'CN' and province = 'Shandong' or view = 'DEFAULT')}";
        };
};
[root@study view]# cat default_view.conf
view "default_view" {
        match-clients {default;};
        dlz "Mysql zone" {
                database "mysql
                {host=127.0.0.1 dbname=example ssl=false port=3306 user=root pass=com}
                {select zone from dns_records where zone = '$zone$' and view = 'DEFAULT' limit 1}
                {select ttl, type, mx_priority, case when lower(type)='txt' then concat('\"', data, '\"') when lower(type)='soa' then concat_ws(' ', data, resp_person, serial, refresh, retry, expire, minimum) else data end as mydata from dns_records where zone= '$zone$' and host = '$record$' and view = 'DEFAULT'}
                {}
                {}
                {}
                {update data_count set count = count + 1 where zone ='$zone$' and view = 'DEFAULT'}";
        };
};
[root@study view]#

2.3 配置数据库内容,包括建表语句,以及插入语句

  step1:建表语句,创建dns_records表,作为BIND9的主要域名解析依据

service mysqld start
mysql -u root -p  //设置mysql的密码
mysql> create database example;    //建立example数据库
use example;
CREATE TABLE `dns_records` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `zone` varchar(255) NOT NULL,
  `host` varchar(255) NOT NULL DEFAULT '@',
  `type` enum('A','MX','CNAME','NS','SOA','PTR','TXT','AAAA','SVR','URL') NOT NULL,
  `data` varchar(255) DEFAULT NULL,
  `ttl` int(11) NOT NULL DEFAULT '3600',
  `mx_priority` int(11) DEFAULT NULL,
  `view` char(20) NOT NULL DEFAULT 'DEFAULT' COMMENT 'name of ISP',
  `country` char(10) NOT NULL DEFAULT 'DEFAULT',
  `province` char(30) NOT NULL DEFAULT 'DEFAULT',
  `priority` tinyint(3) unsigned NOT NULL DEFAULT '255',
  `refresh` int(11) NOT NULL DEFAULT '28800',
  `retry` int(11) NOT NULL DEFAULT '14400',
  `expire` int(11) NOT NULL DEFAULT '86400',
  `minimum` int(11) NOT NULL DEFAULT '86400',
  `serial` bigint(20) NOT NULL DEFAULT '20210810',
  `resp_person` varchar(64) NOT NULL DEFAULT 'ddns.net',
  `primary_ns` varchar(64) NOT NULL DEFAULT 'ns.ddns.net.',
  `data_count` int(11) NOT NULL DEFAULT '0',
  `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0 normal, 1 deleted',
  PRIMARY KEY (`id`),
  KEY `type` (`type`),
  KEY `host` (`host`),
  KEY `zone` (`zone`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

  step2:向dns_records表中插入数据

# 配置正向解析的数据包括一条SOA记录,一条NS记录,一条A记录,两条测试用记录,一个CNAME,一个A记录
INSERT INTO `example`.`dns_records`(`zone`, `host`, `type`, `data`, `ttl`, `mx_priority`, `view`, `country`, `province`, `priority`, `refresh`, `retry`, `expire`, `minimum`, `serial`, `resp_person`, `primary_ns`, `data_count`) VALUES ('bboyxxx.top', '@', 'SOA', 'ns1', 86400, NULL, 'DEFAULT', 'DEFAULT', 'DEFAULT', 255, 3600, 15, 86400, 3600, 2016111600, 'node02.example.com.', 'node02.example.com.', 0);
INSERT INTO `example`.`dns_records`(`zone`, `host`, `type`, `data`, `ttl`, `mx_priority`, `view`, `country`, `province`, `priority`, `refresh`, `retry`, `expire`, `minimum`, `serial`, `resp_person`, `primary_ns`, `data_count`) VALUES ('bboyxxx.top', 'ns1', 'A', '117.73.10.239', 86400, NULL, 'DEFAULT', 'DEFAULT', 'DEFAULT', 255, 3600, 15, 86400, 3600, 2016111600, 'node02.example.com.', 'node02.example.com.', 0);
INSERT INTO `example`.`dns_records`(`zone`, `host`, `type`, `data`, `ttl`, `mx_priority`, `view`, `country`, `province`, `priority`, `refresh`, `retry`, `expire`, `minimum`, `serial`, `resp_person`, `primary_ns`, `data_count`) VALUES ('bboyxxx.top', '@', 'NS', 'ns1.bboyxxx.top.', 86400, NULL, 'DEFAULT', 'DEFAULT', 'DEFAULT', 255, 3600, 15, 86400, 3600, 2016111600, 'node02.example.com.', 'node02.example.com.', 0);
INSERT INTO `example`.`dns_records`(`zone`, `host`, `type`, `data`, `ttl`, `mx_priority`, `view`, `country`, `province`, `priority`, `refresh`, `retry`, `expire`, `minimum`, `serial`, `resp_person`, `primary_ns`, `data_count`) VALUES ('bboyxxx.top', 'fc8f3da3c8a2925084c689e3229a0abb', 'CNAME', 'tudu.vinson.fun.wsdvs.com.', 86400, NULL, 'DEFAULT', 'DEFAULT', 'DEFAULT', 255, 3600, 15, 86400, 3600, 2016111600, 'node02.example.com.', 'node02.example.com.', 0);
INSERT INTO `example`.`dns_records`(`zone`, `host`, `type`, `data`, `ttl`, `mx_priority`, `view`, `country`, `province`, `priority`, `refresh`, `retry`, `expire`, `minimum`, `serial`, `resp_person`, `primary_ns`, `data_count`) VALUES ('bboyxxx.top', 'fc8f3da3c8a2925084c689e3229a0abb', 'A', '111.111.111.111', 3600, NULL, 'CMCC', 'CN', 'Shandong', 255, 28800, 14400, 86400, 86400, 20210810, 'ddns.net', 'ns.ddns.net.', 0);

3. 来吧展示

  host系统为windows操作系统,ipv4地址:192.168.137.1,打开CMD直接用nslookup命令测试fc8f3da3c8a2925084c689e3229a0abb.bboyxxx.top,根据上面配置的acl文件,192.168.137.1这个地址配置在CMCC_CN_Shandong_acl.conf里面,那么按照CUCC_CN_Shandong_view.conf这个view文件的配置,应该返回的结果是111.111.111.111

C:\Users\xxxxxx>nslookup
默认服务器:  JTBJNEWDC002.home.xxxxxx.com
Address:  10.150.1.11

> server 192.168.137.111
默认服务器:  [192.168.137.111]
Address:  192.168.137.111

>  fc8f3da3c8a2925084c689e3229a0abb.bboyxxx.top
服务器:  [192.168.137.111]
Address:  192.168.137.111

名称:    fc8f3da3c8a2925084c689e3229a0abb.bboyxxx.top
Address:  111.111.111.111

  VM机为Linux操作系统,ipv4地址:192.168.137.111,打开terminal直接用nslookup命令测试fc8f3da3c8a2925084c689e3229a0abb.bboyxxx.top,根据上面配置的acl文件,192.168.137.111这个地址配置在default_acl.conf里面,那么按照default_view.conf这个view文件的配置,应该返回的结果是一个CNAME并解析成111.206.176.90

[root@study ~]# nslookup
> server 192.168.137.111
Default server: 192.168.137.111
Address: 192.168.137.111#53
>
> fc8f3da3c8a2925084c689e3229a0abb.bboyxxx.top
Server:         192.168.137.111
Address:        192.168.137.111#53

fc8f3da3c8a2925084c689e3229a0abb.bboyxxx.top    canonical name = tudu.vinson.fun.wsdvs.com.
Name:   tudu.vinson.fun.wsdvs.com
Address: 111.206.176.90

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值