PowerDNS 部署与使用
什么是PowerDNS
?
PowerDNS(PDNS)
成立于20
世纪90
年代末,是开源DNS
软件、服务和支持的主要供应商,它们提供的权威认证DNS
服务器和递归认证DNS
服务器都是100%
开源的软件,同时也和红帽等开源方案提供商一样提供了付费的技术支持版本。同时官方表示为了避免和软件使用者出现竞争,他们只提供服务支持而不提供DNS
托管服务。
和其他的如BIND
、dnsmasq
等将这些功能集成到一起的DNS
软件不同,PowerDNS
将其一分为二,分为了PowerDNS Authoritative Server
和PowerDNS Recursor
,分别对应这两种主要的需求,而我们常说的pdns
指的就是PowerDNS Authoritative Server (后面简称PDNS Auth)
,主要用途就是作为权威域名服务器,当然也可以作为普通的DNS
服务器提供DNS
查询功能,但是自定义域名解析列表没有记录的域名则直接丢弃,不做解析,此时就需要结合PowerDNS-Recursor
使用了。
对于PowerDNS-Recursor
,PowerDNS
官网介绍其是一个内置脚本能力的高性能的DNS
递归查询服务器,并且已经为一亿五千万个互联网连接提供支持。
PowerDNS Authoritative Server
官方文档
PowerDNS Authoritative Server — PowerDNS Authoritative Server documentation
PowerDNS Recursor
官方文档
PowerDNS Recursor — PowerDNS Recursor documentation
部署规划
- 我们公司内网有多个
VLAN
,所以不同网段其实是打通的。 - 请根据实际情况分配
IP
地址。
系统 | 主机名 | IP 地址 |
服务 | 作用 |
---|---|---|---|---|
Centos7.9 | nameserver-sr1-871 | 10.200.1.153 | PowerDNS Authoritative Server | Mater DNS |
Centos7.9 | nameserver-sr2-872 | 10.200.1.154 | PowerDNS Authoritative Server | Slave DNS |
Centos7.9 | nameserver-rs1-860 | 172.16.8.30 | PowerDNS Recursor | DNS1 |
Centos7.9 | nameserver-rs2-861 | 172.16.8.31 | PowerDNS Recursor | DNS2 |
准备工作
4
台服务器均需要操作
# 安装一些包
yum install -y epel-release
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos|g' \
-i.bak \
/etc/yum.repos.d/CentOS-*.repo
sed -e 's!^metalink=!#metalink=!g' \
-e 's!^#baseurl=!baseurl=!g' \
-e 's!http://download\.fedoraproject\.org/pub/epel!https://mirrors.tuna.tsinghua.edu.cn/epel!g' \
-e 's!http://download\.example/pub/epel!https://mirrors.tuna.tsinghua.edu.cn/epel!g' \
-i /etc/yum.repos.d/epel*.repo
yum install -y chrony conntrack ipvsadm ipset jq iptables curl sysstat libseccomp wget socat git gcc-c++ make yum-utils testice-mapper-persistent-data lvm2 bash-completion nfs-utils lrzsz
# 关闭防火墙
systemctl stop firewalld && systemctl disable firewalld
systemctl stop iptables && systemctl disable iptables
# 关闭 Selinux
setenforce 0 && sed -i 's/SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config
# 时间同步
(crontab -l;echo '*/30 * * * * /usr/sbin/ntpdate ntp1.aliyun.com && /usr/sbin/hwclock -w') | crontab
# 内核优化
echo "* - nofile 65535" >> /etc/security/limits.conf
echo "* - nproc 65536" >> /etc/security/limits.conf
sed -i 's#4096#65536#g' /etc/security/limits.d/20-nproc.conf
cat >> /etc/security/limits.d/nofile.conf <<EOF
* soft nofile 65536
* hard nofile 65536
EOF
cat >> /etc/sysctl.conf <<EOF
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 20480
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.core.somaxconn = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_max_tw_buckets = 10240
net.ipv4.ip_forward = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh1 = 2048
net.ipv4.neigh.default.gc_thresh1 = 4096
vm.swappiness = 0
vm.overcommit_memory = 1
vm.panic_on_oom = 0
fs.inotify.max_user_instances = 8192
fs.inotify.max_user_watches = 1048576
fs.file-max = 52706963
fs.nr_open = 52706963
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 10
EOF
sysctl -p >/dev/null 2>&1
# 安装 docker
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
yum makecache fast
yum -y install docker-ce
# 更新系统
yum update -y
# 重启系统
init 6
部署PowerDNS Authoritative Server
Mater DNS
和Slave DNS
上安装PowerDNS Authoritative Server
SQL
初始化语句模板地址
Generic MySQL backend — PowerDNS Authoritative Server documentation
# 安装 PowerDNS Authoritative Server
yum install -y epel-release yum-plugin-priorities &&
curl -o /etc/yum.repos.d/powerdns-auth-48.repo https://repo.powerdns.com/repo-files/el-auth-48.repo &&
yum install -y pdns pdns-backend-mysql.x86_64 mariadb-server
# 连接 mariadb 并配置
systemctl start mariadb
systemctl enable mariadb
mysql -uroot
# 执行以下初始化 sql 语句
create DATABASE pdns;
grant all privileges on pdns.* to pdns@localhost identified by 'pdns';
flush privileges;
use pdns;
CREATE TABLE domains (
id INT AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
master VARCHAR(128) DEFAULT NULL,
last_check INT DEFAULT NULL,
type VARCHAR(8) NOT NULL,
notified_serial INT UNSIGNED DEFAULT NULL,
account VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL,
options VARCHAR(64000) DEFAULT NULL,
catalog VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE UNIQUE INDEX name_index ON domains(name);
CREATE INDEX catalog_idx ON domains(catalog);
CREATE TABLE records (
id BIGINT AUTO_INCREMENT,
domain_id INT DEFAULT NULL,
name VARCHAR(255) DEFAULT NULL,
type VARCHAR(10) DEFAULT NULL,
content VARCHAR(64000) DEFAULT NULL,
ttl INT DEFAULT NULL,
prio INT DEFAULT NULL,
disabled TINYINT(1) DEFAULT 0,
ordername VARCHAR(255) BINARY DEFAULT NULL,
auth TINYINT(1) DEFAULT 1,
PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE INDEX ordername ON records (ordername);
CREATE TABLE supermasters (
ip VARCHAR(64) NOT NULL,
nameserver VARCHAR(255) NOT NULL,
account VARCHAR(40) CHARACTER SET 'utf8' NOT NULL,
PRIMARY KEY (ip, nameserver)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE TABLE comments (
id INT AUTO_INCREMENT,
domain_id INT NOT NULL,
name VARCHAR(255) NOT NULL,
type VARCHAR(10) NOT NULL,
modified_at INT NOT NULL,
account VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL,
comment TEXT CHARACTER SET 'utf8' NOT NULL,
PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE INDEX comments_name_type_idx ON comments (name, type);
CREATE INDEX comments_order_idx ON comments (domain_id, modified_at);
CREATE TABLE domainmetadata (
id INT AUTO_INCREMENT,
domain_id INT NOT NULL,
kind VARCHAR(32),
content TEXT,
PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind);
CREATE TABLE cryptokeys (
id INT AUTO_INCREMENT,
domain_id INT NOT NULL,
flags INT NOT NULL,
active BOOL,
published BOOL DEFAULT 1,
content TEXT,
PRIMARY KEY(id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE INDEX domainidindex ON cryptokeys(domain_id);
CREATE TABLE tsigkeys (
id INT AUTO_INCREMENT,
name VARCHAR(255),
algorithm VARCHAR(50),
secret VARCHAR(255),
PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';
CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);
quit;
Mater DNS
和Slave DNS
上配置PowerDNS Authoritative Server
Mater DNS
# 编辑 PowerDNS Authoritative Server 配置文件
cp /etc/pdns/pdns.conf /etc/pdns/pdns.conf.default
cat /dev/null > /etc/pdns/pdns.conf
# Mater DNS 的配置
vim /etc/pdns/pdns.conf
# 运行模式,no 为非守护进程模式,yes 为守护进程模式
daemon=no
# guardian 进程的启用状态
guardian=no
# 设置运行时的组和用户 ID
setgid=pdns
setuid=pdns
# 日志级别,数值越高,日志越详细
loglevel=9
# 日志记录设施
logging-facility=0
# 缓存 TTL(生存时间)值
cache-ttl=60
# 查询缓存和负查询缓存的 TTL 值
query-cache-ttl=60
negquery-cache-ttl=60
# 分配器和接收器线程数,我的服务器是 4核4线程,仅供参考
distributor-threads=4
receiver-threads=4
# 允许端口重用
reuseport=yes
# 启动的后端类型
launch=gmysql
# MySQL 数据库连接配置
gmysql-host=127.0.0.1
gmysql-dbname=pdns
gmysql-user=pdns
gmysql-password=pdns
# 本地监听地址和端口
local-address=0.0.0.0
local-port=53
# API 的启用及 API 密钥
api=yes
api-key=ITsupport.0
# Web 服务器配置
webserver=yes
webserver-address=0.0.0.0
webserver-allow-from=0.0.0.0/0
webserver-port=8081
webserver-loglevel=detailed
# 设为主服务器
master=yes
# 通知其他服务器地址,这个是 Slave DNS IP
also-notify=10.200.1.154
# 控制AXFR(区域传输)的IP地址范围和禁用状态
allow-axfr-ips=0.0.0.0/0
disable-axfr=no
# 允许从哪些 IP 进行 DNS 更新
allow-dnsupdate-from=0.0.0.0/0
# 从服务器周期检查间隔
slave-cycle-interval=60
# 日志级别,数值越高,日志越详细
loglevel=9
# 配置日志记录
vim /etc/rsyslog.conf
# 底部新增
local0.info /var/log/pdns/pdns.info.log
local0.warn /var/log/pdns/pdns.warn.log
local0.err /var/log/pdns/pdns.err.log
# 授权并手工创建 log 文件
mkdir -p /var/log/pdns
touch /var/log/pdns/pdns.info.log
touch /var/log/pdns/pdns.warn.log
touch /var/log/pdns/pdns.err.log
chmod -R 755 /etc/pdns/pdns.conf /var/log/pdns/
# 启动 Mater DNS
systemctl start pdns
systemctl enable pdns
systemctl restart rsyslog
# 修改启动文件
vim /usr/lib/systemd/system/pdns.service
#ExecStart=/usr/sbin/pdns_server --socket-dir=%t/pdns --guardian=no --daemon=no --disable-syslog --log-timestamp=no --write-pid=no
ExecStart=/usr/sbin/pdns_server --socket-dir=%t/pdns
# 重启 PowerDNS Authoritative Server
systemctl daemon-reload && systemctl restart pdns
Slave DNS
# 编辑 PowerDNS Authoritative Server 配置文件
cp /etc/pdns/pdns.conf /etc/pdns/pdns.conf.default
cat /dev/null > /etc/pdns/pdns.conf
# Slave DNS 的配置
vim /etc/pdns/pdns.conf
# 运行模式,no 为非守护进程模式,yes 为守护进程模式
daemon=no
# guardian 进程的启用状态
guardian=no
# 设置运行时的组和用户 ID
setgid=pdns
setuid=pdns
# 日志级别,数值越高,日志越详细
loglevel=9
# 日志记录设施
logging-facility=0
# 缓存 TTL(生存时间)值
cache-ttl=60
# 查询缓存和负查询缓存的 TTL 值
query-cache-ttl=60
negquery-cache-ttl=60
# 分配器和接收器线程数,我的服务器是 4核4线程,仅供参考
distributor-threads=4
receiver-threads=4
# 允许端口重用
reuseport=yes
# 启动的后端类型
launch=gmysql
# MySQL 数据库连接配置
gmysql-host=127.0.0.1
gmysql-dbname=pdns
gmysql-user=pdns
gmysql-password=pdns
# 本地监听地址和端口
local-address=0.0.0.0
local-port=53
# API 的启用及 API 密钥
api=yes
api-key=ITsupport.0
# Web 服务器配置
webserver=yes
webserver-address=0.0.0.0
webserver-allow-from=0.0.0.0/0
webserver-port=8081
webserver-loglevel=detailed
# 通知其他服务器地址,这个是 Mater DNS IP
also-notify=10.200.1.153
# 控制AXFR(区域传输)的IP地址范围和禁用状态
allow-axfr-ips=0.0.0.0/0
# 允许从哪些 IP 进行 DNS 更新
allow-dnsupdate-from=0.0.0.0/0
# 设为 Slave DNS
slave=yes
# 指定 Mater DNS
master=10.200.1.153
# 配置日志记录
vim /etc/rsyslog.conf
# 底部新增
local0.info /var/log/pdns/pdns.info.log
local0.warn /var/log/pdns/pdns.warn.log
local0.err /var/log/pdns/pdns.err.log
# 授权并手工创建 log 文件
mkdir -p /var/log/pdns
touch /var/log/pdns/pdns.info.log
touch /var/log/pdns/pdns.warn.log
touch /var/log/pdns/pdns.err.log
chmod -R 755 /etc/pdns/pdns.conf /var/log/pdns/
# 启动 Mater DNS
systemctl start pdns
systemctl enable pdns
systemctl restart rsyslog
# 修改启动文件
vim /usr/lib/systemd/system/pdns.service
#ExecStart=/usr/sbin/pdns_server --socket-dir=%t/pdns --guardian=no --daemon=no --disable-syslog --log-timestamp=no --write-pid=no
ExecStart=/usr/sbin/pdns_server --socket-dir=%t/pdns
# 重启 PowerDNS Authoritative Server
systemctl daemon-reload && systemctl restart pdns
Mater DNS
和Slave DNS
上部署web
管理控制台
# 启动 docker
systemctl start docker && systemctl enable docker
# 部署 powerdnsadmin
# SECRET_KEY 随意
mkdir -p /data/powerdnsadmin && chmod 777 /data/powerdnsadmin
docker run -itd --restart=always \
-e SECRET_KEY='ITsupport.0' \
-v /data/powerdnsadmin:/data \
-p 80:80 \
powerdnsadmin/pda-legacy:latest
- 浏览器直接访问
Mater DNS
和Slave DNS
IP
地址配置PowerDNS-Admin
注意区分Mater DNS
和Slave DNS
IP
地址,我的图片实例只有Mater DNS
的配置
- 配置域名解析,测试主从同步
Mater DNS
web
界面配置
Slave DNS
web
界面配置
等待60
秒后,Mater DNS
的解析记录会同步到Slave DNS
我们在Slave DNS
上查看是否正常同步
可以见到,Mater DNS
的解析记录已经自动同步到Slave DNS
。
至此,PowerDNS Authoritative Server
部署完成,并且做了主从(主备)!
部署PowerDNS-Recursor
DNS1
和DNS2
上安装PowerDNS-Recursor
# 安装 PowerDNS-Recursor
yum install -y epel-release yum-plugin-priorities &&
curl -o /etc/yum.repos.d/powerdns-rec-49.repo https://repo.powerdns.com/repo-files/el-rec-49.repo &&
yum install -y pdns-recursor
DNS1
和DNS2
上配置PowerDNS-Recursor
# 编辑 DNS1 和 DNS2 配置文件
cp /etc/pdns-recursor/recursor.conf /etc/pdns-recursor/recursor.conf.bak
cat /dev/null > /etc/pdns-recursor/recursor.conf
vim /etc/pdns-recursor/recursor.conf
# 运行 PowerDNS Recursor 作为守护进程
daemon=yes
# 监听所有的 IP 地址
local-address=0.0.0.0
# 允许所有 IP 地址的查询
allow-from=0.0.0.0/0
# 在端口53上监听 DNS 查询
local-port=53
# 将所有查询转发到指定的 DNS 服务器
forward-zones-recurse=.=223.5.5.5;202.96.128.86;119.29.29.29
# 从文件加载转发区域的配置
forward-zones-file=/etc/pdns-recursor/zones
# 缓存中的最大记录数
max-cache-entries=800000
# 负缓存条目的最大生存时间(TTL)
max-negative-ttl=10
# 在日志条目中包含时间戳
log-timestamp=yes
# 日志级别
loglevel=6
# 运行进程的组和用户身份
setgid=pdns-recursor
setuid=pdns-recursor
# 禁用 DNSSEC,非特殊情况都请禁用
dnssec=off
# 启用并配置内置的 web 服务器,用于 API 和监控
webserver=yes
webserver-address=0.0.0.0
webserver-port=8081
webserver-allow-from=0.0.0.0/0
api-key=ITsupport.0
# 日志记录设施
logging-facility=1
# 详细日志,必要时可以开起来
#trace=yes
# 使用4个线程
threads=4
# 允许的最大同时查询线程数,看需求
#max-mthreads=4
# 禁用查询分发
pdns-distributes-queries=no
# 启用 SO_REUSEPORT,允许多个进程/线程共享同一个端口
reuseport=yes
# 将线程绑定到特定的 CPU 核心
cpu-map=0=0 1=1 2=2 3=3
# 编写 DNS1 和 DNS2 转发区域
# 可以理解为哪些域转发到内部的权威 DNS 解析服务器
vim /etc/pdns-recursor/zones
# 后面两个 IP 为 `Mater DNS`和 `Slave DNS` 地址
+itwordsweb.net=10.200.1.153;10.200.1.154
# 修改 DNS1 和 DNS2 启动文件
vim /usr/lib/systemd/system/pdns-recursor.service
#ExecStart=/usr/sbin/pdns_recursor --socket-dir=%t/pdns-recursor --daemon=no --write-pid=no --disable-syslog --log-timestamp=no
ExecStart=/usr/sbin/pdns_recursor --socket-dir=%t/pdns-recursor --daemon=no --write-pid=no
# 配置 DNS1 和 DNS2 日志记录
vim /etc/rsyslog.conf
# 底部新增
local1.info /var/log/pdns/pdns-recursor.info.log
local1.warn /var/log/pdns/pdns-recursor.warn.log
local1.err /var/log/pdns/pdns-recursor.err.log
# DNS1 和 DNS2 授权并手工创建 log 文件
mkdir -p /var/log/pdns
touch /var/log/pdns/pdns-recursor.info.log
touch /var/log/pdns/pdns-recursor.warn.log
touch /var/log/pdns/pdns-recursor.err.log
chmod -R 755 /etc/pdns-recursor/recursor.conf /etc/pdns-recursor/zones /var/log/pdns/
# 启动服务
systemctl daemon-reload && systemctl restart rsyslog
systemctl enable pdns-recursor && systemctl start pdns-recursor
- 本地电脑配置
DNS
服务器为DNS1
和DNS2
的地址
- 测试是否生效
通过测试可见,DNS
服务器已经被识别为DNS1
的地址,并且访问 www.baidu.com
时正常返回,访问 www.itwordsweb.net
时会被转发。
- 模拟
DNS1
宕机,测试一下
# DNS1上把pdns-recursor停止
systemctl stop pdns-recursor
- 继续测试
可以看到,当DNS1
宕机,DNS2
会正常接管DNS
解析服务。
至此,整套PowerDNS
,包含PowerDNS Authoritative Server
和PowerDNS-Recursor
部署完成,并测试通过!