介绍
powerdns + mysql + webadmin 简单管理域名服务器系统环境
centos 或者 debian申请域名,并把域名解析权转移到自己的服务器上
申请域名服务器,推荐到 namecheap 申请,申请完成域名以后,需要把自己的域名转移到自己的dns服务器中,方法如下,折腾好namecheap 以后,开始自己搭建 dns server安装mysql server 及必须的软件包
debianapt-get install mysql-server mysql-client pdns-server pdns-backend-mysqlcentos
yum install pdns-backend-mysql -y
软件包安装完成以后,开始配置
- mysql server 配置
[...] bind-address = 127.0.0.1 [...]然后重启 mysql server
- 创建 powerdns 默认是数据库
mysql -u root -p# 创建所需数据库 CREATE DATABASE powerdns; # 为powerdns 数据库创建用户并指派权限, power_admin_password 为密码,可以自己修改 GRANT ALL ON powerdns.* TO 'power_admin'@'localhost' IDENTIFIED BY 'power_admin_password'; GRANT ALL ON powerdns.* TO 'power_admin'@'localhost.localdomain' IDENTIFIED BY 'power_admin_password'; FLUSH PRIVILEGES; # 导入基本数据 USE powerdns; # 创建基本的表 CREATE TABLE domains ( id INT auto_increment, name VARCHAR(255) NOT NULL, master VARCHAR(128) DEFAULT NULL, last_check INT DEFAULT NULL, type VARCHAR(6) NOT NULL, notified_serial INT DEFAULT NULL, account VARCHAR(40) DEFAULT NULL, primary key (id) ); # 创建索引 CREATE UNIQUE INDEX name_index ON domains(name); # CREATE TABLE records ( id INT auto_increment, domain_id INT DEFAULT NULL, name VARCHAR(255) DEFAULT NULL, type VARCHAR(6) DEFAULT NULL, content VARCHAR(255) DEFAULT NULL, ttl INT DEFAULT NULL, prio INT DEFAULT NULL, change_date INT DEFAULT NULL, primary key(id) ); # CREATE INDEX rec_name_index ON records(name); CREATE INDEX nametype_index ON records(name,type); CREATE INDEX domain_id ON records(domain_id); # CREATE TABLE supermasters ( ip VARCHAR(25) NOT NULL, nameserver VARCHAR(255) NOT NULL, account VARCHAR(40) DEFAULT NULL); # 退出 quit
- 编辑powerdns 配置文件 /etc/powerdns/pdns.conf ,使其使用mysql 数据库,找到如下字段,修改如下, recursor 表示如果查询的域名不在本机上,则向上级域名服务器查询,查询的地址为 192.168.1.254
[...] # 注释如下行 ################################# # allow-recursion List of netmasks that are allowed to recurse allow-recursion#allow-recursion ################################# # launch Which backends to launch and order to query them in # # launch= launch=gmysql[...] ################################# # recursor If recursion is desired, IP address of a recursing nameserver # recursor=192.168.1.254 #################################
debian 需要如下步骤
修改如下文件vim /etc/powerdns/pdns.d/pdns.local修改成如下
# Here comes the local changes the user made, like configuration of # the several backends that exists. gmysql-host=127.0.0.1 gmysql-user=power_admin gmysql-password=power_admin_password gmysql-dbname=powerdns
centos 需要如下步骤
centos 的系统,不需要创建 pdns.local 文件,直接把上面的几句话,添加到 pdns.conf 文件的末尾,如下gmysql-host=127.0.0.1 gmysql-user=power_admin gmysql-password=power_admin_password gmysql-dbname=powerdns然后重启 powernds 服务
/etc/init.d/pdns restart到此步骤,powernds 安装设定完毕
检查安装是否成功
打开日志文件 tail /var/log/messages,内容应该如下Jan 10 15:59:43 ip-10-150-167-111 pdns[29860]: TCP server bound to 0.0.0.0:53 Jan 10 15:59:43 ip-10-150-167-111 pdns[29860]: PowerDNS 2.9.22 (C) 2001-2009 PowerDNS.COM BV (Dec 14 2010, 18:18:42, gcc 4.4.4 20100726 (Red Hat 4.4.4-13)) starting upJan 10 15:59:43 ip-10-150-167-111 pdns[29860]: PowerDNS comes with ABSOLUTELY NO WARRANTY. This is free software, \ and you are welcome to redistribute it according to the terms of the GPL version 2. Jan 10 15:59:43 ip-10-150-167-111 pdns[29860]: Creating backend connection for TCPJan 10 15:59:43 ip-10-150-167-111 pdns[29860]: gmysql Connection succesfulJan 10 15:59:43 ip-10-150-167-111 pdns[29860]: About to create 3 backend threads for UDPJan 10 15:59:43 ip-10-150-167-111 pdns[29860]: gmysql Connection succesfulJan 10 15:59:43 ip-10-150-167-111 pdns[29860]: gmysql Connection succesfulJan 10 15:59:43 ip-10-150-167-111 pdns[29860]: gmysql Connection succesfulJan 10 15:59:43 ip-10-150-167-111 pdns[29860]: Done launching threads, ready to distribute questions
安装 powerdns admin
基于web的管理方式,很好用
apt-get install apache2 libapache2-mod-php5 php5 php5-common\ php5-curl php5-dev php5-gd php-pear php5-imap php5-mcrypt\ php5-mhash php5-ming php5-mysql php5-xmlrpc gettext如果提示如下,选 yes
Continue installing libc-client without Maildir support? <-- Yes
debian 系统
安装完成基本包以后,安装如下pear install DB pear install pear/MDB2#mysql
centos 系统
yum install php-pear-DB php-pear-MDB2 php-pear-MDB2-Driver-mysqli php-pear-MDB2-Driver-mysqlphp包安装完成以后,下载 powerdns admin 软件包,并配置 其官方网站为 https://www.poweradmin.org/trac/wiki/GettingPoweradmin 下载开始安装,最新的为 2.1.5
cd /tmp wget https://www.poweradmin.org/download/poweradmin-2.1.5.tgz tar xvfz poweradmin-2.1.5.tgz mkdir -p /var/www/poweradmin mv poweradmin-2.1.5/* /var/www/poweradmin touch /var/www/poweradmin/inc/config.inc.php chown -R www-data:www-data /var/www/poweradmin/安装完成以后,打开浏览器 如 (http://server1.example.com/poweradmin/install or http://192.168.0.100/poweradmin/install).
继续下一步
继续,输入 mysql 的root 密码,非 刚才创建的 powerdns 用户的密码 ,这里注意哦
继续,这里输入power_admin 密码,也就是创建的 powerdns 的数据库密码,主机名就是你的主机名字,nameserver 就是你刚才在namecheap 注册的dns 名字,一般自己写个就可以了
接着下一步
继续
继续,默认即可
系统为了安装期间,安装完成以后,需要删除 install 目录
rm -fr /var/www/poweradmin/install/到这里,web管理页面安装完成,输入 http://server1.example.com/poweradmin or http://192.168.0.100/poweradmin 看看吧
创 建 zone, go to Add master zone and fill in the domain name (e.g. example.com). You can already fill in the IP addresses for the www A record ("webserver") and the MX record ("mailserver") for that zone. If you leave the Create zone without applying records-template checkbox unchecked, Poweradmin will automatically create some NS, A (e.g. www) and MX records for that zone.
FROM http://code.google.com/p/unxmail/wiki/powerdns
---------------
yum -y install httpd php php-devel php-gd php-imap php-ldap php-mysql php-odbc php-pear php-xml php-xmlrpc php-mbstring php-mcrypt php-mhash gettext
yum install php-pear-DB php-pear-MDB2-Driver-mysql
wget http://soft.laozuo.org/powerdns/poweradmin-2.1.7.tgz
tar zxvfpoweradmin-2.1.7
mv poweradmin-2.1.7 /var/www/html/poweradmin
touch /var/www/html/poweradmin/inc/config.inc.php
chown -R apache:apache /var/www/html/poweradmin/
# 外网权威服务器(可以多个)
# 对于本地并没有记录的域名将转发到其他递归DNS服务器解析
recursor=8.8.8.8
recursor=119.29.29.29
# 开启的线程数(根据访问量设置)
distributor-threads=100
# 最大链接数(根据访问量设置)
max-tcp-connections=1000
#web控制面板默认端口:8081(可以用于通过web监控DNS服务器的解析数据)
webserver=yes
webserver-address=0.0.0.0
The most common way to set up PowerDNS (pdns) on multiple servers (ns1, ns2, etc…) is to enable MySQL replication from the master (ns1) and the slave(s) (ns2, ns3). That’s going to be part 2 of this HOWTO. Let’s just get pdns set up on our master and answering queries for now…
First, let’s make sure mysql is installed:
1
2
| yum install mysql mysql-server -y |
Let’s edit the /etc/my.cnf file and make sure that skip-networking is commented out
1
2
| #skip-networking |
Now make sure it starts when booting into levels 2, 3, 5 and we can start it up
1
2
3
| chkconfig --levels 235 mysqld on service mysqld start |
Check via netstat that mysql is listening on all interfaces:
1
2
3
| netstat -tap | grep "*:mysql" tcp 0 0 *:mysql *:* LISTEN 20319 /mysqld |
Set the mysql root password (without it showing up in your bash history!)
1
2
3
| /usr/bin/mysql_secure_installation (follow the prompts /questions ) |
Now we’re ready to install powerdns:
1
2
| yum install pdns pdns-backend-mysql |
Connect to mysql, create the database, set the permissions, add some tables for pdns: (make sure to replace ‘pdns_admin_pass’ with something else!)
1
2
3
| mysql -u root -p CREATE DATABASE powerdns; |
Modify the following two lines with your own password
1
2
3
| GRANT ALL ON powerdns.* TO 'pdns_admin' @ 'localhost' IDENTIFIED BY 'pdns_admin_pass' ; GRANT ALL ON powerdns.* TO 'pdns_admin' @ 'localhost.localdomain' IDENTIFIED BY 'pdns_admin_pass' ; |
Feel free to paste the rest of this in all at once
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
| FLUSH PRIVILEGES; USE powerdns; CREATE TABLE domains ( id INT auto_increment, name VARCHAR(255) NOT NULL, master VARCHAR(128) DEFAULT NULL, last_check INT DEFAULT NULL, type VARCHAR(6) NOT NULL, notified_serial INT DEFAULT NULL, account VARCHAR(40) DEFAULT NULL, primary key ( id ) ); CREATE UNIQUE INDEX name_index ON domains(name); CREATE TABLE records ( id INT auto_increment, domain_id INT DEFAULT NULL, name VARCHAR(255) DEFAULT NULL, type VARCHAR(6) DEFAULT NULL, content VARCHAR(255) DEFAULT NULL, ttl INT DEFAULT NULL, prio INT DEFAULT NULL, change_date INT DEFAULT NULL, primary key( id ) ); CREATE INDEX rec_name_index ON records(name); CREATE INDEX nametype_index ON records(name, type ); CREATE INDEX domain_id ON records(domain_id); CREATE TABLE supermasters ( ip VARCHAR(25) NOT NULL, nameserver VARCHAR(255) NOT NULL, account VARCHAR(40) DEFAULT NULL ); |
No issues? Ok, quit out..
1
2
| quit |
Edit /etc/pdns/pdns.conf and tell it how to connect:
1
2
3
4
5
6
| launch=gmysql gmysql-host=127.0.0.1 gmysql-user=pdns_admin gmysql-password=pdns_admin_password gmysql-dbname=powerdns |
Make sure pdns starts on boot & start it up:
1
2
3
| chkconfig --levels 235 pdns on service pdns start |
This server should now answer on domains its authoritative for. Other domains, however, it has no idea. Let’s tell pdns to look at another server for recursion. Edit the /etc/pdns/pdns.conf file and modify your recursion lines:
1
2
3
4
5
| # allow recursion for our subnet only (default allows recursion for everyone) allow-recursion=192.168.0.0 /24 # recursion server recursor=192.168.0.1 |
Web based frontend:There are many web based frontends out there for pdns. We’re going to use ‘PowerDNS-Webinterface‘ It’s a great looking, simple GUI that uses easy templates so that you can make it your own once you’re done. Plus, it has multi-user support – create sub-accounts for your users!
Let’s make sure we have some pre-reqs installed:
1
2
| yum install httpd php php-mysql gettext -y |
Make sure you’re running at least PHP 5.2:
1
2
3
4
| php - v PHP 5.3.8 (cli) (built: Oct 31 2011 18:26:52) Copyright (c) 1997-2011 The PHP Group |
Download the latest powerdns-webinterface package: http://code.google.com/p/powerdns-webinterface/downloads/list Unpack it and install:
1
2
3
4
5
6
7
| tar zxvf powerdns-webinterface-1.4.1. tar .gz cd powerdns-webinterface mysql -u pdns_admin -p powerdns < install .sql mv web/* /var/www/html/ chmod 777 /var/www/html/tmp/templates_c vim /var/www/html/configs/db .php (enter your db info) |
PowerDNS是高性能的域名服务器,除了支持普通的BIND配置文件,PowerDNS还可以从 MySQL,Oracle,PostgreSQL等的数据库读取数据。PowerDNS安装了Poweradmin,能实现Web管理DNS记录,非常的 方便。本文我们以MySQL为后端数据库和Poweradmin网页管理DNS,在CentOS-5安装PowerDNS。
安装MySQL
yum -y install mysql mysql-server设置mysql开机自启并启动mysql
chkconfig –levels 235 mysqld on修改mysql root密码:
/etc/init.d/mysqld start
mysqladmin -u root password yourrootsqlpassword安装PowerDNS
yum -y install pdns pdns-backend-mysql连接mysql:
mysql -u root -p创建powerdns数据库:
CREATE DATABASE powerdns;为PowerDNS创建powerdns数据库用户:
GRANT ALL ON powerdns.* TO ‘power_admin’@'localhost’ IDENTIFIED BY ‘power_admin_password’;请替换power_admin_password成自己的密码。
FLUSH PRIVILEGES;
现在创建数据表:
USE powerdns;
CREATE TABLE domains (
id INT auto_increment,
name VARCHAR(255) NOT NULL,
master VARCHAR(128) DEFAULT NULL,
last_check INT DEFAULT NULL,
type VARCHAR(6) NOT NULL,
notified_serial INT DEFAULT NULL,
account VARCHAR(40) DEFAULT NULL,
primary key (id)
);
CREATE UNIQUE INDEX name_index ON domains(name);
CREATE TABLE records (
id INT auto_increment,
domain_id INT DEFAULT NULL,
name VARCHAR(255) DEFAULT NULL,
type VARCHAR(6) DEFAULT NULL,
content VARCHAR(255) DEFAULT NULL,
ttl INT DEFAULT NULL,
prio INT DEFAULT NULL,
change_date INT DEFAULT NULL,
primary key(id)
);
CREATE INDEX rec_name_index ON records(name);
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE TABLE supermasters (最后退出mysql shell:
ip VARCHAR(25) NOT NULL,
nameserver VARCHAR(255) NOT NULL,
account VARCHAR(40) DEFAULT NULL
);
quit;现在配置PowerDNS以使用mysql后端:
vi /etc/pdns/pdns.conf增加如下内容到pdns.conf
[...]设置PowerDNS自启动并立即启动PowerDNS。
#################################
# launch Which backends to launch and order to query them in
#
# launch=
launch=gmysql
gmysql-host=127.0.0.1
gmysql-user=power_admin
gmysql-password=power_admin_password
gmysql-dbname=powerdns
[...]
chkconfig –levels 235 pdns on现在PowerDNS已经正常运行,下面我们为PowerDNS安装Poweradmin实现Web管理。
/etc/init.d/pdns start
安装Poweradmin
Poweradmin运行在PHP环境中,我们现在配置Web环境。
yum -y install httpd php php-devel php-gd php-imap php-ldap php-mysql php-odbc php-pear php-xml php-xmlrpc php-mbstring php-mcrypt php-mhash gettext设置apache自启动,并启动apache。
chkconfig –levels 235 httpd onPoweradmin还需要安装两个PEAR软件包。
/etc/init.d/httpd start
yum install php-pear-DB php-pear-MDB2-Driver-mysql现在Poweradmin所需的环境已经配置完成,我们将把Poweradmin安装在目录/var/www/html,这是apache默认的文档根目录。
到https://www.poweradmin.org/trac/wiki/GettingPoweradmin找到最新的版本下载:
cd /tmp然后安装在/var/www/html/poweradmin目录。
wget https://www.poweradmin.org/download/poweradmin-2.1.5.tgz
tar xvfz poweradmin-2.1.5.tgz------------------
mv poweradmin-2.1.5 /var/www/html/poweradmin
touch /var/www/html/poweradmin/inc/config.inc.php
chown -R apache:apache /var/www/html/poweradmin/
安装MySQL
设置mysql开机自启并启动mysql
安装PowerDNS
连接mysql:
为PowerDNS创建powerdns数据库用户:
GRANT ALL ON powerdns.* TO 'power_admin'@'localhost' IDENTIFIED BY 'power_admin_password';
USE powerdns;
CREATE TABLE domains (
CREATE TABLE supermasters (
现在配置PowerDNS以使用mysql后端:
现在PowerDNS已经正常运行,下面我们为PowerDNS安装Poweradmin实现Web管理。
设置apache自启动,并启动apache。
现在Poweradmin所需的环境已经配置完成,我们将把Poweradmin安装在目录/var/www/html,这是apache默认的文档根目录。
然后安装在/var/www/html/poweradmin目录。
2、点击“Go to step 3”到安装的第三步,填入数据库详细信息。输入root用户和密码,和输入Poweradmin的admin用户的密码。
3、点击下一步,填入在安装powerdns那一步所创建的power_admin mysql用户的信息,并且填入域名服务器地址。
5、继续点击下一步。
6、现在poweradmin安装完成。
7、为了安全,需要删除安装目录。
现在你可以进入http://www.urdomain.com/poweradmin或者http://192.168.0.100/poweradmin页面,输入用户admin和执行安装程序时设置的密码进入管理界面。
POWERDNS WITH SQLITE
Generic SQLite backend (2 and 3)
Native | Yes |
Master | Yes |
Slave | Yes |
Superslave | Yes |
DNSSEC | gsqlite3 only (set gsqlite3-dnssec) |
Module name | gsqlite and gsqlite3 |
Launch name | gsqlite and gsqlite3 |
Warning | |
---|---|
When importing large amounts of data, be sure to run ‘analyze;’ afterwards as SQLite3 has a tendency to use sub-optimal indexes otherwise. |
5.1. Compiling the SQLite backend
When you’ve installed the library you can use: ./configure –with-modules=”gsqlite” or ./configure –with-modules=”gsqlite3″ to configure PowerDNS to use the SQLite backend. Compilation can then proceed as usual.
SQLite is included in most PowerDNS binary releases.
5.2. Setting up the database
create table domains ( id INTEGER PRIMARY KEY, name VARCHAR(255) NOT NULL COLLATE NOCASE, master VARCHAR(128) DEFAULT NULL, last_check INTEGER DEFAULT NULL, type VARCHAR(6) NOT NULL, notified_serial INTEGER DEFAULT NULL, account VARCHAR(40) DEFAULT NULL ); CREATE UNIQUE INDEX name_index ON domains(name); CREATE TABLE records ( id INTEGER PRIMARY KEY, domain_id INTEGER DEFAULT NULL, name VARCHAR(255) DEFAULT NULL, type VARCHAR(10) DEFAULT NULL, content VARCHAR(65535) DEFAULT NULL, ttl INTEGER DEFAULT NULL, prio INTEGER DEFAULT NULL, change_date INTEGER DEFAULT NULL ); CREATE INDEX rec_name_index ON records(name); CREATE INDEX nametype_index ON records(name,type); CREATE INDEX domain_id ON records(domain_id); create table supermasters ( ip VARCHAR(25) NOT NULL, nameserver VARCHAR(255) NOT NULL COLLATE NOCASE, account VARCHAR(40) DEFAULT NULL );
This schema contains all elements needed for master, slave and superslave operation.
To support DNSSEC, or to migrate to DNSSEC, the following statements must be issued:
alter table records add ordername VARCHAR(255); alter table records add auth bool; create index orderindex on records(ordername); create table domainmetadata ( id INTEGER PRIMARY KEY, domain_id INT NOT NULL, kind VARCHAR(16) COLLATE NOCASE, content TEXT ); create index domainmetaidindex on domainmetadata(domain_id); create table cryptokeys ( id INTEGER PRIMARY KEY, domain_id INT NOT NULL, flags INT NOT NULL, active BOOL, content TEXT ); create index domainidindex on cryptokeys(domain_id); create table tsigkeys ( id INTEGER PRIMARY KEY, name VARCHAR(255) COLLATE NOCASE, algorithm VARCHAR(50) COLLATE NOCASE, secret VARCHAR(255) ); create unique index namealgoindex on tsigkeys(name, algorithm);
For full migration notes, please see Section 3, “Migration”.
After you have created the database you probably want to fill it with data. If you have a BIND zone file it’s as easy as: zone2sql –zone=myzonefile –gmysql | sqlite powerdns.sqlite, but you can also use AXFR (or insert data manually).
To communicate with a SQLite database, use either the ‘sqlite’ or ‘sqlite3′ program, and feed it SQL.
5.3. Using the SQLite backend
# in pdns.conf launch=gsqlite # or gsqlite3 gsqlite-database=<path to your SQLite database> # or gsqlite3-database
https://github.com/fwenzel/powerdns-dyndns
-------------
编译powerdns
(文档:https://doc.powerdns.com/md/appendix/compiling-powerdns/#compiling-powerdns)
首先要编译boost:(参见http://www.briten.info/2016/08/boostsockssocksserver.html)
wget http://downloads.sourceforge.net/project/boost/boost/1.61.0/boost_1_61_0.tar.bz2
tar jxvf boost_1_61_0.tar.bz2
cd boost_1_61_0
root@AR:~/boost_1_61_0# ls
b2 boost-build.jam bootstrap.bat index.htm libs rst.css
bin.v2 boostcpp.jam bootstrap.log index.html LICENSE_1_0.txt stage
bjam boost.css bootstrap.sh INSTALL more status
boost boost.png doc Jamroot project-config.jam tools
root@AR:~/boost_1_61_0# ./bootstrap.sh
root@AR:~/boost_1_61_0# ./b2 (此步骤耗时1 hour to 2 hours and 34 minutes)或者./bjam
root@AR:~/boost_1_61_0# ./b2 install或者./bjam install
这样,boost就编译好了。
(装好后,默认的头文件在/usr/local/include/boost目录下。库文件在/usr/local/lib/目录下。默认不用修改。如果编译好程序后,在运行时提示无法加载某个库文件,则把/usr/local/lib下的所有boost的库文件mv到/usr/lib目录下就可以了。)
wget https://downloads.powerdns.com/releases/pdns-4.2.0-rc2.tar.bz2
tar jxvf pdns-4.2.0-rc2.tar.bz2
cd pdns-4.2.0-rc2
./configure --disable-lua-records
make && make install
但是运行 which pdns ,没有显示pdns在哪里。
----------------------------------------------------------
自建 PowerDNS 智能解析服务器
优缺点
- 如果那天自己的服务器挂了,整个域名相关服务都会挂,即使你邮件收信服务器是用的是第三方的,你也不能收信了
- 基本上必须是开放端口,并有固定 IP(而且最好还需要至少两个 IP) 的 VPS(当然也可以是两个主机,只需要保证配置文件完全相同即可),对于服务提供商要求高
- 个人一般关于 DNS 运维经验不足,容易导致配置错误
- 第三方 DNS 提供商基本都有 DDOS 防御,而你的服务器可不一定有,攻击者可以直接通过 L7 DNS Flood 攻击掉你的服务器,然后又回到第一个问题上了
- 可 DIY 程度极大,各种 DNS 方面功能几乎都能配置,但却又都十分复杂
- 可以建在已有的服务器上,不用额外花钱
- EDNS Client Subnet
- DNSSEC
- GEODNS
- IPv6
简述安装过程
pdns-server
,然后再安装 pdns-backend-$backend
。Backend 是你可以自己选的,常用的有 BIND
和 Generic MySQL
,需要 GEODNS 可以用 GEOIP
,所有列表见此。如果想做网页版控制后台,使用 MySQL 的可能比较方便。如果只是通过文件形式控制,那么 BIND 和 GEOIP 都可以。$ sudo apt install pdns-server
$ sudo apt install pdns-backend-geoip
$ rm /etc/powerdns/pdns.d/* # 删除 Example
安装更新版本的 PowerDNS
安装地理位置数据库
/etc/GeoIP.conf
内容是:# The following UserId and LicenseKey are required placeholders:
UserId 999999
LicenseKey 000000000000
# Include one or more of the following ProductIds:
# * GeoLite2-City - GeoLite 2 City
# * GeoLite2-Country - GeoLite2 Country
# * GeoLite-Legacy-IPv6-City - GeoLite Legacy IPv6 City
# * GeoLite-Legacy-IPv6-Country - GeoLite Legacy IPv6 Country
# * 506 - GeoLite Legacy Country
# * 517 - GeoLite Legacy ASN
# * 533 - GeoLite Legacy City
ProductIds 506 GeoLite-Legacy-IPv6-Country
DatabaseDirectory /usr/share/GeoIP
sudo apt install geoipupdate && mkdir -p /usr/share/GeoIP && geoipupdate -v
,你的数据库就已经下载完毕了。配置 PowerDNS
/etc/powerdns/pdns.d/geoip.conf
内容是:launch=geoip
geoip-database-files=/usr/share/GeoIP/GeoLiteCountry.dat /usr/share/GeoIP/GeoIPv6.dat # 选择 IPv4 和 IPv6 国家模块
geoip-database-cache=memory
geoip-zones-file=/share/zone.yaml # 你的 YAML 配置文件的位置,随便哪个地方都行
geoip-dnssec-keydir=/etc/powerdns/key
# @see: https://doc.powerdns.com/md/authoritative/backend-geoip/
domains:
- domain: example.com
ttl: 300 # 默认 TTL 时长
records:
##### Default NS
ns1.example.com:
- a: # 你的服务器的第一个 IPv4 地址
content: 10.0.0.1
ttl: 86400
- aaaa: # 你的服务器的第一个 IPv6 地址
content: ::1
ttl: 86400
ns2.example.com: # 你的服务器的第二个 IPv4 地址(如果没有就和上面一样)
- a:
content: 10.0.0.2
ttl: 86400
- aaaa: # 你的服务器的第二个 IPv6 地址(如果没有就和上面一样)
content: ::2
ttl: 86400
##### Root domain
example.com: # 根域名下的记录
- soa:
content: ns1.example.com. admin.example.com. 1 86400 3600 604800 10800
ttl: 7200
- ns:
content: ns1.example.com.
ttl: 86400
- ns:
content: ns2.example.com.
ttl: 86400
- mx:
content: 100 mx1.example.com. # 权重 [空格] 主机名
ttl: 7200
- mx:
content: 100 mx2.example.com.
ttl: 7200
- mx:
content: 100 mx3.example.com.
ttl: 7200
- a: 103.41.133.70 # 如果想使用默认 TTL,那就不用区分 content 和 ttl 字段
- aaaa: 2001:470:fa6b::1
##### Servers list 你的服务器列表
beijing-server.example.com: &beijing
- a: 10.0.1.1
- aaaa: ::1:1
newyork-server.example.com: &newyork
- a: 10.0.2.1
- aaaa: ::2:1
japan-server.example.com: &japan
- a: 10.0.3.1
- aaaa: ::3:1
london-server.example.com: &uk
- a: 10.0.4.1
- aaaa: ::4:1
france-server.example.com: &france
- a: 10.0.5.1
- aaaa: ::5:1
##### GEODNS 分区解析
# @see: https://php.net/manual/en/function.geoip-continent-code-by-name.php
# @see: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3
# unknown also is default
# %co.%cn.geo.example.com
# 默认
unknown.unknown.geo.example.com: *newyork # 默认解析到美国
# 洲
unknown.as.geo.example.com: *japan # 亚洲解析到日本
unknown.oc.geo.example.com: *japan # 大洋洲解析到日本
unknown.eu.geo.example.com: *france # 欧洲解析到法国
unknown.af.geo.example.com: *france # 非洲解析到法国
# 国家
chn.as.geo.example.com: *beijing # 中国解析北京
gbr.eu.geo.example.com: *uk # 英国解析到英国
services:
# GEODNS
www.example.com: [ '%co.%cn.geo.example.com', 'unknown.%cn.geo.example.com', 'unknown.unknown.geo.example.com']
配置域名
$ dig icann.org ns +short
a.iana-servers.net.
b.iana-servers.net.
c.iana-servers.net.
ns.icann.org.
$ dig org ns +short
a2.org.afilias-nst.info.
b0.org.afilias-nst.org.
d0.org.afilias-nst.org.
c0.org.afilias-nst.info.
a0.org.afilias-nst.info.
b2.org.afilias-nst.org.
$ dig @a0.org.afilias-nst.info icann.org ns
;; QUESTION SECTION:
;icann.org. IN NS
;; AUTHORITY SECTION:
icann.org. 86400 IN NS c.iana-servers.net.
icann.org. 86400 IN NS a.iana-servers.net.
icann.org. 86400 IN NS ns.icann.org.
icann.org. 86400 IN NS b.iana-servers.net.
;; ADDITIONAL SECTION:
ns.icann.org. 86400 IN A 199.4.138.53
ns.icann.org. 86400 IN AAAA 2001:500:89::53
YAML 的一些高级写法
&variable
设置变量,*variable
使用变量,这很像 CloudXNS 下的 LINK 记录,比如在 CloudXNS 下你可以这么写:www.example.com 600 IN A 10.0.0.1
www.example.com 600 IN A 10.0.0.2
www.example.com 600 IN AAAA ::1
www.example.com 600 IN AAAA ::2
sub.example.com 600 IN LINK www.example.com
www.example.com: &www
- a: 10.0.0.1
- a: 10.0.0.2
- aaaa: ::1
- aaaa: ::2
sub.example.com: *www
添加 DNSSEC 支持
$ mkdir /etc/powerdns/key $ pdnsutil secure-zone example.com $ pdnsutil show-zone example.com
其他一些有趣的东西
"*.ip.example.com":
- txt:
content: "IP%af: %ip, Continent: %cn, Country: %co, ASn: %as, Region: %re, Organisation: %na, City: %ci"
ttl: 0
$ random=`head -200 /dev/urandom | md5` ; dig ${random}.ip.example txt +short
"IPv4: 42.83.200.23, Continent: as, Country: chn, ASn: unknown, Region: unknown, Organisation: unknown, City: unknown"
进阶使用
建立分布式 DNS
$ dig @a.gtld-servers.net mydmain.com
;; QUESTION SECTION:
;mydmain.com. IN A
;; AUTHORITY SECTION:
mydmain.com. 172800 IN NS a.geo.ns.tloxygen.net.
mydmain.com. 172800 IN NS c.geo.ns.tloxygen.net.
;; ADDITIONAL SECTION:
a.geo.ns.tloxygen.net. 172800 IN A 198.251.90.65
a.geo.ns.tloxygen.net. 172800 IN AAAA 2605:6400:10:6a9::2
c.geo.ns.tloxygen.net. 172800 IN A 104.196.241.116
c.geo.ns.tloxygen.net. 172800 IN AAAA 2605:6400:20:b5e::2
Anycast or Unicast?
宕机自动切换
自建 PowerDNS 进阶:分区解析,dnsdist,Lua 记录
- 本文适用于最新的 PowerDNS 4.2.0
- 使用 MaxMind GeoIP 2 mmdb 格式的数据库
- 讲述如何为根域名设置分区解析
- 使用 dnsdist 以实现 IP 访问速率的限制,防御 DOS 攻击。
安装 PowerDNS Authoritative Server 和 dnsdist
pdns-server
和 pdns-backend-geoip
即可。在 Debian/Ubuntu 下:sudo apt-get install pdns-server pdns-backend-geoip
systemd-resolved
服务,这个服务占用了 loopback 地址的的 53 端口,这与 PowerDNS 所需要使用的端口(0.0.0.0:53
)冲突。你可以:1. 禁用这个服务,2. 修改 PowerDNS 的 local-address 和 local-ipv6 配置仅监听外网 IP 地址,3. 修改 local-port 为非 53 端口,并使用 dnsdist 进行转发(详见后文)。sudo apt-get install dnsdist
禁用 systemd-resolved
sudo systemctl disable systemd-resolved.service
sudo systemctl stop systemd-resolved
安装 geoipupdate 并下载 GeoIP2
/etc/GeoIP.conf
为如下内容(包含了 IPv4 和 IPv6 的国家、城市、ASN 数据):ProductIds GeoLite2-Country GeoLite2-City GeoLite2-ASN
DatabaseDirectory /usr/share/GeoIP
sudo add-apt-repository ppa:maxmind/ppa
sudo apt update
sudo apt install geoipupdate
sudo geoipupdate -v
配置 PowerDNS
/etc/powerdns
,首先删除 PowerDNS 原本的 demo 配置,然后建立文件夹以存储 DNSSEC 的密钥文件:sudo rm /etc/powerdns/pdns.d/*
sudo mkdir /etc/powerdns/keys
/etc/powerdns/pdns.d/geoip.conf
为如下内容:launch=geoip
geoip-database-files=/usr/share/GeoIP/GeoLite2-Country.mmdb /usr/share/GeoIP/GeoLite2-City.mmdb /usr/share/GeoIP/GeoLite2-ASN.mmdb
geoip-zones-file=/etc/powerdns/zones.yaml
geoip-dnssec-keydir=/etc/powerdns/key
geoip-database
选项中,你可以按照需要设置自己所需要的一个或多个 GeoIP 数据库。配置 DNS 记录
/etc/powerdns/zones.yaml
以配置 DNS 记录。具体格式参见 Zonefile format。%re
是 ISO3166 的两位区域缩写。若使用 dat,则是 GeoIP 的区域代码。domains:
- domain: example.com
ttl: 300
records:
unknown.cn.example.com:
- soa: &soa ns1.example.com hostmaster.example.com 2014090125 7200 3600 1209600 3600
- ns: &ns1
content: ns1.example.com
ttl: 600
- ns: &ns2 ns2.example.com
- mx: &mx 10 mx.example.com
- a: 10.1.1.1
bj.cn.example.com:
- soa: *soa
- ns: *ns1
- ns: *ns2
- mx: *mx
- a: 10.1.2.1
unknown.unknown.example.com:
- soa: *soa
- ns: *ns1
- ns: *ns2
- mx: *mx
- a: 10.1.3.1
ns1.example.com:
- a: 10.0.1.1
- aaaa: ::1
ns2.example.com:
- a: 10.0.2.1
services:
example.com: [ '%ci.%cc.service.geo.example.com', 'unknown.%cc.service.geo.example.com', 'unknown.unknown.service.geo.example.com']
&variable
设置变量,*variable
使用变量)调试
debug.tlo.xyz:
- a: "%ip4"
- aaaa: "%ip6"
- txt: "co: %co; cc: %cc; cn: %cn; af: %af; re: %re; na: %na; as: %as; ci: %ci; ip: %ip"
10.11.12.13
为服务所监听的 IP 地址),有如下结果:$ dig @10.11.12.13 debug.example.com
debug.example.com. 3600 IN TXT "co: us; cc: us; cn: na; af: v4; re: ca; na: quadranet enterprises llc; as: 8100; ci: los angeles; ip: 10.11.12.13"
debug.example.com. 3600 IN A 10.11.12.13
Lua 记录
enable-lua-records=yes
sub.example.com:
- lua: A "ifportup(443, {'192.0.2.1', '192.0.2.2'})"
sub.example.com:
- lua: A "ifurlup('https://sub.example.com/', {{'192.0.2.1', '192.0.2.2'}, {'198.51.100.1'}})"
配置 dnsdist
127.0.0.1:8053
。创建或修改文件 /etc/dnsdist/dnsdist.conf
为以下内容:newServer{address="127.0.0.1:8053",useClientSubnet=true}
setLocal("10.0.1.1")
setACL({'0.0.0.0/0', '::/0'})
setECSSourcePrefixV4(32)
setECSSourcePrefixV6(128)
addAction(MaxQPSIPRule(10, 32, 56), TCAction())
addAction(MaxQPSIPRule(20, 32, 56), DropAction())
addAction(MaxQPSIPRule(40, 24, 48), TCAction())
addAction(MaxQPSIPRule(80, 24, 48), DropAction())
addAction(MaxQPSIPRule(160, 16, 40), TCAction())
addAction(MaxQPSIPRule(320, 16, 40), DropAction())
newServer
语句设置了 dnsdist 所代理的服务器,也就是 pdns 所监听的 IP 地址和端口号。setLocal
设置了 dnsdist 的监听 ip 地址。setACL
设置了允许的 IP 地址,这里允许了所有的 IPv6 和 IPv4 访问。setECSSourcePrefixV4
和 setECSSourcePrefixV6
设置了 EDNS Client Subnet Client 功能传输 IP 地址的比特数,这里为 IPv4 设置了 32 位,IPv6 设置了 128 位,也就是保留了 IP 地址的完整长度。实际生产中也可以设置比这个更小的值。addAction
和 MaxQPSIPRule
定义了访问速率限制。其中 MaxQPSIPRule
拥有三个参数。第一个参数是 qps,即 queries per second,每秒钟请求数。第二个参数是 IPv4 的 CIDR 值,默认为 32,第三个参数是 IPv6 的 CIDR 值,默认为 64。TCAction
代表要求客户端使用 TCP 请求,DropAction
代表拒绝请求。普通的客户端在收到 DNS 服务器要求使用 TCP 时,会使用 TCP 进行 DNS 请求,这样不影响普通用户的使用。而 DOS 一般不会对 TCP DNS 服务进行攻击。addAction(MaxQPSIPRule(40, 24, 48), TCAction())
Self-built PowerDNS GeoDNS Server
Today, I changed the DNS server to a self-built one, and shared my experience (PS: Now in order to realize the root domain CDN, I used Route 53 instead):
The self-built DNS in this article refers to the authoritative DNS, that is, the DNS configured for your own domain name, not the cache DNS configured on the client.
Advantages and Disadvantages
First of all, let me talk about the fatal disadvantages of using a self-built DNS server:
- If your server is down that day, the entire domain name related services will be down. Even if your mail receiving server is a third-party, you will not be able to receive mail.
- Basically, it must be a VPS with an open port and a fixed IP (and preferably at least two IPs) (of course it can be two hosts, just make sure that the configuration files are exactly the same), High requirements for service providers
- Individuals generally have insufficient experience in DNS operation and maintenance, which can easily lead to configuration errors
- Third-party DNS providers basically have DDOS defense, but your server may not have it. An attacker can directly attack your server through L7 DNS Flood, and then go back to the first problem.
Advantages of using a self-built DNS server:
- The degree of DIY is extremely high, almost all DNS functions can be configured, but they are all very complicated
- Can be built on an existing server without extra cost
In the end, I chose to use PowerDNS software (which is actually used by many service providers that provide DNS services). I installed its recently released version 4.0. Some features supported by this version:
- EDNS Client Subnet
- DNSSEC
*GEODNS - IPv6
Wait, that’s just what came to my mind. At the same time, PowerDNS supports many types of resolution records (at least the most I have seen so far): A, AAAA, AFSDB, ALIAS (also ANAME), CAA, CERT, CDNSKEY, CDS, CNAME, DNSKEY, DNAME, DS, HINFO, KEY, LOC, MX, NAPTR, NS, NSEC, NSEC3, NSEC3PARAM, OPENPGPKEY, PTR, RP, RRSIG, SOA, SPF, SSHFP, SRV, TKEY, TSIG, TLSA, TXT, URI, etc., and there are no columns that are not commonly used out, see all supported records. To be honest, there are some unpopular records that many resolvers do not support, but I need to use them, such as LOC, SSHFP and TLSA. Don’t know what this pile of records is for? See Wikipedia.
Briefly Describe the Installation Process
For detailed installation method see official documentation, you need to install pdns-server
first, and then install pdns-backend-$backend
. Backend is something you can choose by yourself. Commonly used ones are BIND
and Generic MySQL
. If you need GEODNS, you can use GEOIP
. All lists see here . If you want to control the background of the web version, it may be more convenient to use MySQL. Both BIND and GEOIP are fine if it is only controlled by file. I use the GEOIP version. The GEOIP version is highly scalable and uses YAML files, which is more flexible and elegant. This article will talk about the GEOIP version: Install on Ubuntu (available in the system software source):
$ sudo apt install pdns-server
$ sudo apt install pdns-backend-geoip
Then modify the configuration file:
$ rm /etc/powerdns/pdns.d/* # delete Example
Install a Newer Version of PowerDNS
Many features, such as CAA records, require the new version of PowerDNS. Please go to the official website to configure the software source.
Install Geolocation Database
Note that you should already have the MaxMind GeoIP Lite database, if not, install it as follows:
Important update⚠️: Since April 1, 2018, the GeoIP database in DAT format cannot be automatically downloaded by the software. Please [go to the official website to manually download the corresponding database](https://dev.maxmind.com/geoip/legacy/geolite /). It needs to be in Binary format.
Create a file /etc/GeoIP.conf
with:
# The following UserId and LicenseKey are required placeholders:
UserId 999999
LicenseKey 000000000000
# Include one or more of the following ProductIds:
# * GeoLite2-City - GeoLite 2 City
# * GeoLite2-Country - GeoLite2 Country
# * GeoLite-Legacy-IPv6-City - GeoLite Legacy IPv6 City
# * GeoLite-Legacy-IPv6-Country - GeoLite Legacy IPv6 Country
# * 506 - GeoLite Legacy Country
# * 517 - GeoLite Legacy ASN
# * 533 - GeoLite Legacy City
ProductIds 506 GeoLite-Legacy-IPv6-Country
DatabaseDirectory /usr/share/GeoIP
Then install geoipupdate, execute sudo apt install geoipupdate && mkdir -p /usr/share/GeoIP && geoipupdate -v
, your database has been downloaded.
Configure PowerDNS
Create a file /etc/powerdns/pdns.d/geoip.conf
with:
launch=geoip
geoip-database-files=/usr/share/GeoIP/GeoLiteCountry.dat /usr/share/GeoIP/GeoIPv6.dat # Select IPv4 and IPv6 country modules
geoip-database-cache=memory
geoip-zones-file=/share/zone.yaml # The location of your YAML configuration file, anywhere
geoip-dnssec-keydir=/etc/powerdns/key
Create that YAML file, and then start writing Zone, here is an example (IPv6 is not required, all IPs should be filled in with external IPs, this article takes the country as an example, the order of the juxtaposed content does not matter):
# @see: https://doc.powerdns.com/md/authoritative/backend-geoip/
domains:
- domain: example.com
ttl: 300 # Default TTL duration
records:
##### Default NS
ns1.example.com:
- a: # Your server's first IPv4 address
content: 10.0.0.1
ttl: 86400
- aaaa: # Your server's first IPv6 address
content: ::1
ttl: 86400
ns2.example.com: # Second IPv4 address of your server (if not, same as above)
- a:
content: 10.0.0.2
ttl: 86400
- aaaa: # Second IPv6 address of your server (if not, same as above)
content: ::2
ttl: 86400
##### Root domain
example.com: # records under the root domain name
- soa:
content: ns1.example.com.admin.example.com.1 86400 3600 604800 10800
ttl: 7200
- ns:
content: ns1.example.com.
ttl: 86400
- ns:
content: ns2.example.com.
ttl: 86400
- mx:
content: 100 mx1.example.com. # weight [space] hostname
ttl: 7200
- mx:
content: 100 mx2.example.com.
ttl: 7200
- mx:
content: 100 mx3.example.com.
ttl: 7200
- a: 103.41.133.70 # If you want to use the default TTL, you don't need to distinguish between the content and ttl fields
- aaaa: 2001:470:fa6b::1
##### Servers list Your server list
beijing-server.example.com: &beijing
- a: 10.0.1.1
- aaaa: ::1:1
newyork-server.example.com: &newyork
- a: 10.0.2.1
- aaaa: ::2:1
japan-server.example.com: &japan
- a: 10.0.3.1
- aaaa: ::3:1
london-server.example.com: &uk
- a: 10.0.4.1
- aaaa: ::4:1
france-server.example.com: &france
- a: 10.0.5.1
- aaaa: ::5:1
##### GEODNS partition resolution
# @see: https://php.net/manual/en/function.geoip-continent-code-by-name.php
# @see: https://en.wikipedia.org/wiki/ISO\_3166-1\_alpha-3
# unknown also is default
# %co.%cn.geo.example.com
# default
unknown.unknown.geo.example.com: *newyork # resolves to US by default
# continent
unknown.as.geo.example.com: *japan # Asia to Japan
unknown.oc.geo.example.com: *japan # Oceania resolves to Japan
unknown.eu.geo.example.com: *france # Europe resolves to France
unknown.af.geo.example.com: *france # Africa to France
# nation
chn.as.geo.example.com: *beijing # China parsing Beijing
gbr.eu.geo.example.com: *uk # UK resolves to UK
services:
#GEODNS
www.example.com: [ '%co.%cn.geo.example.com', 'unknown.%cn.geo.example.com', 'unknown.unknown.geo.example.com']
This configuration is equivalent to parsing www.example.com to the partition. Due to some problems in this parsing at present, GEODNS cannot be set under the root domain name and subdomain at the same time. I have submitted feedback on this bug. (https://github .com/PowerDNS/pdns/issues/4276). If you want to only set the parsing precision at the continent level, just write %cn.geo.example.com one less level. If you need to be accurate to the city, you can write one more level, but you need to add the GeoIP city database to the configuration file. However, the city version of the free city database is not accurate, and you also need to purchase a commercial database, which is an additional cost.
Configure the Domain Name
Go to your domain name registrar, enter the background to modify the settings, and add a subdomain name server record to the domain name, as shown in the figure:
Since the NS to be set is under your own server, you must register your NS server IP address with the upper-level domain name (such as .com) on the domain name registrar, so that the upper-level domain name can resolve the IP of the NS and build your own DNS For example, there is a NS of its own under icann.org:
$ dig icann.org ns +short
a.iana-servers.net.
b.iana-servers.net.
c.iana-servers.net.
ns.icann.org.
Then look at its upper-level domain name org:
$ dig org ns +short
a2.org.afilias-nst.info.
b0.org.afilias-nst.org.
d0.org.afilias-nst.org.
c0.org.afilias-nst.info.
a0.org.afilias-nst.info.
b2.org.afilias-nst.org.
Find any server and query the authoritative record (I don’t need +short ):
$ dig @a0.org.afilias-nst.info icann.org ns
;; QUESTION SECTION:
;icann.org.INNS
;; AUTHORITY SECTION:
icann.org.86400INNSc.iana-servers.net.
icann.org.86400INNSa.iana-servers.net.
icann.org.86400INNSns.icann.org.
icann.org.86400INNSb.iana-servers.net.
;; ADDITIONAL SECTION:
ns.icann.org.86400INA199.4.138.53
ns.icann.org.86400INAAAA2001:500:89::53
It can be seen that the NS server in this org has already returned the records of ns.icann.org. This is why you need to fill in the IP address in the domain name registrar. However you’d better return the same NS and the same IP on the DNS server under your domain name as well. Finally, don’t forget to change the NS record of the domain name.
Some Advanced Writing of YAML
In the YAML I just used, I have actually used the advanced YAML writing method, that is, &variable
sets variables, *variable
uses variables, which is very similar to the LINK record under CloudXNS, for example, under CloudXNS you can write:
www.example.com 600 IN A 10.0.0.1
www.example.com 600 IN A 10.0.0.2
www.example.com 600 IN AAAA ::1
www.example.com 600 IN AAAA ::2
sub.example.com 600 IN LINK www.example.com
Then in your YAML record you can write:
www.example.com: &www
- a: 10.0.0.1
- a: 10.0.0.2
- aaaa: ::1
- aaaa: ::2
sub.example.com: *www
This is a high-level way of writing YAML without any additional support.
Add DNSSEC support
For details, you can Reference Documentation, run the following command:
$ mkdir /etc/powerdns/key
$ pdnsutil secure-zone example.com
$ pdnsutil show-zone example.com
The result returned by the last command is the record you need to set at the domain name registrar. It is not recommended to set all of them. Just set ECDSAP256SHA256 - SHA256 digest. Finally, check the settings online Test address 1 Test address 2, there may be a few days of caching time. My inspection results
Some Other Interesting Stuff
You can write this in YAML, to make it easier for you to debug:
"*.ip.example.com":
- TXT:
content: "IP%af: %ip, Continent: %cn, Country: %co, ASn: %as, Region: %re, Organisation: %na, City: %ci"
ttl: 0
These variables can be used as your GEODNS criteria, as well as checking your GEOIP database. Then, check the posture correctly:
$ random=`head -200 /dev/urandom md5` ; dig ${random}.ip.example txt +short
"IPv4: 42.83.200.23, Continent: as, Country: chn, ASn: unknown, Region: unknown, Organisation: unknown, City: unknown"
The IP address is the DNS cache server address (if you enable EDNS Client Subnet and the cache server supports it, then it is your own IP, but if you use 8.8.8.8, you will see that the last digit of your IP is 0), if you If you specify to check from your own server locally, then return your own IP address directly. Since I only have the country database installed, everything is Unknown except for the continent and country.
Advanced Use
Establish Distributed DNS
In general, it is a DNS resolution server of a Master and a Slave, but in this case, there may be problems with DNSSEC, so I set up two Master servers, automatically synchronize records, and set same DNSSEC Private Key , nothing seems to go wrong (after all, all records, including SOA, are exactly the same), my server’s current configuration
$ dig @a.gtld-servers.net guozeyu.com
;; QUESTION SECTION:
;guozeyu.com.INA
;; AUTHORITY SECTION:
guozeyu.com.172800INNSa.geo.ns.tloxygen.net.
guozeyu.com.172800INNSc.geo.ns.tloxygen.net.
;; ADDITIONAL SECTION:
a.geo.ns.tloxygen.net.172800INA198.251.90.65
a.geo.ns.tloxygen.net.172800INAAAA2605:6400:10:6a9::2
c.geo.ns.tloxygen.net.172800INA104.196.241.116
c.geo.ns.tloxygen.net.172800INAAAA2605:6400:20:b5e::2
Among them are two IPv4 and two IPv6, of which a.geo.ns.tloxygen.net. is an IP address using Anycast technology, which is provided by three servers behind it. c.geo.ns.tloxygen.net. belongs to the host of another service provider, so there is a backup after it hangs, which is more stable.
Anycast or Unicast?
A distributed DNS like mine is actually a combination of Unicast and Anycast. One problem is that connecting to one of them in one place will be faster, but the other will be slower. Only with a DNS cache server that supports asynchronous query or with GeoIP, it is possible to connect to the fastest DNS authoritative server, otherwise it is a random connection, and if a server hangs, then the corresponding IP of the server is obsolete. Anycast is an IP corresponding to multiple hosts, but I have no conditions to use it. This may cost more for individuals. Either you have an AS number and let the host provider give you access, or your host provider provides cross-regional access. Load Balancing IP. My VPS is in two different hosting companies, and I don’t have AS, so I can’t use Anycast. I think Anycast should be used for DNS services, because the IP corresponding to the DNS server cannot be GEODNS (because this is the root domain name that is resolved for you). After using Anycast, the fastest connection rate can basically be guaranteed, and a server has an IP address. Still usable. Additionally, DNS must forward both TCP and UDP port 53.
Automatically Switch when Downtime
How to realize automatic switchover when downtime? The process to achieve this is: Monitoring service finds downtime -> Sends a downtime request to the server -> The server processes the downtime, resolves to an alternate IP/pauses parsing monitoring service finds that the service is normal -> Sends a normal service request to the server -> The server processes the service normally, and the recovery analysis can create two YAML files, one is used by default, and the other is used when the server is down. When the monitoring service finds that the server is down, reload another YAML file, and then this is Downtime mode.
Self-built PowerDNS Advanced: GeoDNS, dnsdist, Lua Records
This article will talk about setting up your own DNS authoritative server (serving your own domain name, this is not a public DNS cache server) using PowerDNS’s GeoIP Backend.
By using PowerDNS, you can build a DNS server that supports partition resolution (fine to country, city, ASN, custom IP segment), EDNS-Client-Subnet, DNSSEC, IPv6 on your own server.
This article is for domain name owners and webmasters, and is about authoritative DNS servers, not DNS caching servers. If you want to know more about DNS, please refer to Detailed Explanation of DNS Domain Name Resolution System - Basics and 'Introduction to DNSSEC, How Signatures Work'.(https://www.ze3kr.com/2018/03/dnssec/)
This article is an update to ‘self-built PowerDNS intelligent resolution server’. The advantages and disadvantages of self-built DNS, configuring DNSSEC, and distributed DNS services are described in the previous article, which will be omitted in this article. This article mainly updates the following content:
- This article applies to the latest PowerDNS 4.2.0
- Use the database in MaxMind GeoIP 2 mmdb format
- Describe how to set partition resolution for the root domain name
- Use dnsdist to limit IP access rate and defend against DOS attacks.
Install PowerDNS Authoritative Server and dnsdist
Considering the different default versions of operating system software sources, it is recommended to go to PowerDNS repositories reconfigure the software sources for PowerDNS Authoritative Server (please Add 4.2 or above). You can also configure dnsdist’s repositories (please add version 1.2 or above).
After adding the repositories, update the software list and install pdns-server
and pdns-backend-geoip
. Under Debian/Ubuntu:
sudo apt-get install pdns-server pdns-backend-geoip
It should be noted that the systemd-resolved
service may be included by default after Ubuntu 18.04 LTS. This service occupies port 53 of the loopback address, which conflicts with the port (0.0.0.0:53
) required by PowerDNS. . You can: 1. Disable this service, 2. Modify PowerDNS’s local-address and [local-ipv6](https: //doc.powerdns.com/md/authoritative/settings/#local-ipv6) Configure to listen to external network IP addresses only, 3. Modify [local-port](https://doc.powerdns.com/md/authoritative/ settings/#local-port) is a non-53 port and forwarded using dnsdist (see below for details).
If you want to configure the user-side IP access rate, install dnsdist:
sudo apt-get install dnsdist
Disable systemd-resolved
If you choose to disable systemd-resolved
, you can execute the following code:
sudo systemctl disable systemd-resolved.service
sudo systemctl stop systemd-resolved
Install geoipupdate and download GeoIP2
To implement partition resolution, we need the GeoIP database. The latest version of PowerDNS GeoIP Backend (4.2.0) already supports the mmdb format of GeoIP2, and also supports the dat format. The boss’s database only supports dat format. Since MaxMind has discontinued maintaining a free dat format database, it is highly recommended to use PowerDNS version 4.2 and above and use mmdb format instead IP database**.
First create a configuration file, create /etc/GeoIP.conf
with the following content (including IPv4 and IPv6 country, city, and ASN data):
ProductIds GeoLite2-Country GeoLite2-City GeoLite2-ASN
DatabaseDirectory /usr/share/GeoIP
It is recommended to install geoipupdate, which can be installed in Ubuntu as follows:
sudo add-apt-repository ppa:maxmind/ppa
sudo apt update
sudo apt install geoipupdate
Then download/update GeoIP2:
sudo geoipupdate -v
All done!
It is also recommended to configure Crontab to periodically execute the above command to update the database file (and reload the PowerDNS service) to update the GeoIP database.
Configure PowerDNS
The configuration file of PowerDNS (hereinafter referred to as pdns) is located in /etc/powerdns
. First delete the original demo configuration of PowerDNS, and then create a folder to store the DNSSEC key file:
sudo rm /etc/powerdns/pdns.d/*
sudo mkdir /etc/powerdns/keys
Then create the file, create /etc/powerdns/pdns.d/geoip.conf
with the following content:
launch=geoip
geoip-database-files=/usr/share/GeoIP/GeoLite2-Country.mmdb /usr/share/GeoIP/GeoLite2-City.mmdb /usr/share/GeoIP/GeoLite2-ASN.mmdb
geoip-zones-file=/etc/powerdns/zones.yaml
geoip-dnssec-keydir=/etc/powerdns/key
In the geoip-database
option, you can set up one or more GeoIP databases as needed.
Configure DNS records
You can create the file /etc/powerdns/zones.yaml
to configure DNS records. For the specific format, see Zonefile format.
It should be noted that if mmdb is used, %re
is the two-digit regional abbreviation for ISO3166. If using dat, it is the region code for GeoIP.
Since PowerDNS GeoIP Backend only supports partition resolution by domain name configuration, and does not support partition resolution by record configuration, so to configure root domain name partition resolution, you can refer to the following configuration (YAML format, the same below):
domains:
- domain: example.com
ttl: 300
records:
unknown.cn.example.com:
- soa: &soa ns1.example.com hostmaster.example.com 2014090125 7200 3600 1209600 3600
- ns: &ns1
content: ns1.example.com
ttl: 600
- ns: &ns2 ns2.example.com
- mx: &mx 10 mx.example.com
- a: 10.1.1.1
bj.cn.example.com:
- soa: *soa
- ns: *ns1
-ns: *ns2
- mx: *mx
- a: 10.1.2.1
unknown.unknown.example.com:
- soa: *soa
- ns: *ns1
-ns: *ns2
- mx: *mx
- a: 10.1.3.1
ns1.example.com:
- a: 10.0.1.1
- aaaa: ::1
ns2.example.com:
- a: 10.0.2.1
services:
example.com: [ '%ci.%cc.service.geo.example.com', 'unknown.%cc.service.geo.example.com', 'unknown.unknown.service.geo.example.com']
As you can see, in order to configure sub-regional resolution of the domain name, we need to configure all types of records for each region. The root domain name usually has many record types, so it is relatively cumbersome to configure. The above YAML writing uses variables, which can reduce the repeated records of configuration. (&variable
sets variables, *variable
uses variables)
debug
You can debug by configuring logging as follows:
debug.tlo.xyz:
- a: "%ip4"
- aaaa: "%ip6"
- txt: "co: %co; cc: %cc; cn: %cn; af: %af; re: %re; na: %na; as: %as; ci: %ci; ip: %ip"
Tested on the client through a command similar to the following (replace 10.11.12.13
with the IP address the service is listening on), and the following results are obtained:
$ dig @10.11.12.13 debug.example.com
debug.example.com. 3600 IN TXT "co: us; cc: us; cn: na; af: v4; re: ca; na: quadranet enterprises llc; as: 8100; ci: los angeles; ip: 10.11.12.13 "
debug.example.com.3600 IN A 10.11.12.13
This way you can see the specific value of each variable.
Lua records
In PowerDNS 4.2, Lua logging feature. The main function of its Lua record is that it can be configured to automatically switch records when downtime.
Since Lua records can use the Lua programming language to execute arbitrary code, which is relatively dangerous, PowerDNS disables this function by default and needs to be enabled in the configuration file:
enable-lua-records=yes
Configure the following records, which will return dynamically available A records. If the ports of both IPs are available (here is port 443), an IP address will be returned randomly, if one is unavailable, only the address of the available IP will be returned, otherwise both IPs will be returned at the same time:
sub.example.com:
- lua: A "ifportup(443, {'192.0.2.1', '192.0.2.2'})"
Configure the following records to automatically check the status of the specified URL. By default, the first group of IP addresses will be returned. If the first group of IP addresses is unavailable, the second group will be returned:
sub.example.com:
- lua: A "ifurlup('https://sub.example.com/', {{'192.0.2.1', '192.0.2.2'}, {'198.51.100.1'}})"
Lua records can be used with GeoIP functionality and can coexist with other types of records. In addition, the status check is not synchronized with the request, but periodically checks whether it is available in the background, so using the status check will not increase the delay of DNS requests.
configure dnsdist
By now, your DNS server should be working. Configuring dnsdist is described below.
dnsdist is equivalent to adding a layer of proxy on top of pdns, which can be configured to limit the access rate and play an anti-DOS role. Under normal circumstances, after the installation of dnsdist is completed, its service will start automatically.
In this example, change the main program listener of pdns to 127.0.0.1:8053
. Create or modify the file /etc/dnsdist/dnsdist.conf
with the following content:
newServer{address="127.0.0.1:8053",useClientSubnet=true}
setLocal("10.0.1.1")
setACL({'0.0.0.0/0', '::/0'})
setECSSourcePrefixV4(32)
setECSSourcePrefixV6(128)
addAction(MaxQSIPRule(10, 32, 56), TCAction())
addAction(MaxQSIPRule(20, 32, 56), DropAction())
addAction(MaxQSIPRule(40, 24, 48), TCAction())
addAction(MaxQSIPRule(80, 24, 48), DropAction())
addAction(MaxQSIPRule(160, 16, 40), TCAction())
addAction(MaxQSIPRule(320, 16, 40), DropAction())
The newServer
statement sets the server proxied by dnsdist, which is the IP address and port number on which pdns listens. setLocal
sets the listening ip address of dnsdist. setACL
sets the allowed IP addresses, here all IPv6 and IPv4 access is allowed. setECSSourcePrefixV4
and setECSSourcePrefixV6
set the number of bits of the IP address transmitted by the EDNS Client Subnet Client function. Here, 32 bits are set for IPv4, and 128 bits are set for IPv6, that is, the full length of the IP address is reserved. A smaller value than this can also be set in actual production.
The last few lines addAction
and MaxQPSIPRule
define the access rate limit. Where MaxQSIPRule
has three parameters. The first parameter is qps, which is queries per second, the number of requests per second. The second parameter is the CIDR value for IPv4, which defaults to 32, and the third parameter is the CIDR value for IPv6, which defaults to 64. TCAction
represents asking the client to use a TCP request, and DropAction
represents rejecting the request. When an ordinary client receives a request from the DNS server to use TCP, it will use TCP to make a DNS request, which does not affect the use of ordinary users. DOS generally does not attack the TCP DNS service.
For example, the following statement means:
addAction(MaxQSIPRule(40, 24, 48), TCAction())
Limits the qps of /24 IPv4 addresses (256) and /48 IPv6 addresses (2^80) to 40, if it exceeds, the client is required to use TCP requests.
In addition to TCAction and DropAction, DelayAction (an integer parameter representing the number of milliseconds to delay) and NoRecurseAction (specifically to limit requests marked with recursion ((RD))) can also be used.
Therefore, using dnsdist with pdns can make the DNS service have a certain anti-DOS ability.