PowerDNS的部署与使用

发布时间 2023-04-24 12:40:17作者: 厚礼蝎

PowerDNS简介

PowerDNS成立于上世纪90年代后期,是开源DNS的主要供应商

目前主要产品有Authoritative Server、Recursor和Dnsdist产品,目前是完全开源的

PowerDNS也有商业化的产品支持,其用户和客户包括了全球领先的电信服务供应商、大型集成商及财富500强软件公司,在斯堪的纳维亚、德国和荷兰,PowerDNS是域名服务器软件的第一大供应商。

与bind不同,powerDNS的权威和递归服务是分开的服务

作为权威域名服务器

安装

#这里以mysql作为后端存储服务,所以这里安装的是pdns-backend-mysql
yum install pdns pdns-backend-mysql

#也可以指定版本安装,例如,要安装4.6版本的
yum install -y epel-release yum-plugin-priorities &&
curl -o /etc/yum.repos.d/powerdns-auth-46.repo https://repo.powerdns.com/repo-files/el-auth-46.repo &&
yum install pdns -y

可以通过 yum list pdns-backend* | grep 4.6 来查看可用的4.6版本的后端所有存储驱动

安装存储数据库

这里以mysql作为例子,为了方便,这里使用docker-compose镜像部署

version: '3'
services:
  mysql:
    image: mysql:8.0
    container_name: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 111111
      #MYSQL_ALLOW_EMPTY_PASSWORD: yes
      MYSQL_DATABASE: powerdns
      MYSQL_USER: powerdns
      MYSQL_PASSWORD: powerdns
    volumes:
    - ./db:/var/lib/mysql
    - ./etc/my.cnf:/etc/my.cnf
    - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime
    ports:
    - 3306:3306
    command:
      #为了能远程登录root,所以修改了验证模块,生产中建不开启
      - --default-authentication-plugin=mysql_native_password

docker-compose.yaml文件同目录下的新建etc目录,用来存放mysql配置文件

配置文件内容

vim ./etc/my.cnf

[mysqld]
port        = 3306
#socket      = /tmp/mysql.sock
datadir = /var/lib/mysql/var
skip-external-locking
key_buffer_size = 32M
max_allowed_packet = 1M
table_open_cache = 128
sort_buffer_size = 768K
net_buffer_length = 8K
read_buffer_size = 768K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M
thread_cache_size = 16
tmp_table_size = 32M
performance_schema_max_table_instances = 1000

explicit_defaults_for_timestamp = true
#skip-networking
max_connections = 500
max_connect_errors = 100
open_files_limit = 65535

log-bin=mysql-bin
binlog_format=mixed
server-id   = 1
expire_logs_days = 10
early-plugin-load = ""

default_storage_engine = InnoDB
innodb_file_per_table = 1
innodb_data_home_dir = /var/lib/mysql/var
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /var/lib/mysql/var
innodb_buffer_pool_size = 128M
innodb_log_file_size = 32M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip_name_resolve=on

部署容器

docker-compose up -d

新建相关表

mysql -u powerdns -ppowerdns
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)
) Engine=InnoDB;
 
CREATE UNIQUE INDEX name_index ON domains(name);
 
CREATE TABLE records (
  id                    BIGINT AUTO_INCREMENT,
  domain_id             INT DEFAULT NULL,
  name                  VARCHAR(255) DEFAULT NULL,
  type                  VARCHAR(10) DEFAULT NULL,
  content               BLOB(64000) DEFAULT NULL,
  ttl                   INT DEFAULT NULL,
  prio                  INT DEFAULT NULL,
  change_date           INT DEFAULT NULL,
  disabled              TINYINT(1) DEFAULT 0,
  ordername            VARCHAR(255) BINARY DEFAULT NULL,
  auth                  TINYINT(1) DEFAULT 1,
  PRIMARY KEY (id)
) Engine=InnoDB;
 
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE INDEX recordorder ON records (domain_id, ordername);
 
CREATE TABLE supermasters (
  ip                    VARCHAR(64) NOT NULL,
  nameserver            VARCHAR(255) NOT NULL,
  account               VARCHAR(40) NOT NULL,
  PRIMARY KEY (ip, nameserver)
) Engine=InnoDB;
 
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) NOT NULL,
  comment               BLOB(64000) NOT NULL,
  PRIMARY KEY (id)
) Engine=InnoDB;
 
CREATE INDEX comments_domain_id_idx ON comments (domain_id);
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;
 
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,
  content               TEXT,
  PRIMARY KEY(id)
) Engine=InnoDB;
 
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;
 
CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);
 
flush privileges;

pdns配置

vim /etc/pdns/pdns.conf

#设置数据库相关的
launch=gmysql
gmysql-host=10.0.0.10
gmysql-port=3306
gmysql-dbname=powerdns
#管理数据库的相关用户和密码
gmysql-user=powerdns
gmysql-password=powerdns
#访问权限
allow-axfr-ips=0.0.0.0/0,::1
allow-dnsupdate-from=0.0.0.0/0,::1
allow-notify-from=0.0.0.0/0,::/0
allow-unsigned-notify=yes
also-notify=10.0.0.10
#daemon 启动
daemon=yes
disable-axfr=no
guardian=no
#是否master
master=yes
#是否slave
slave=no
#启动权限
setgid=pdns
setuid=pdns
#打印日志
log-dns-details=yes
log-dns-queries=no
loglevel=6
log-timestamp=yes
logging-facility=0
#开启api
api=yes
api-key=dnsadmin1syn
#启动webserver 监控
webserver=yes
webserver-address=0.0.0.0
webserver-allow-from=0.0.0.0/0
webserver-port=8081
#监听的地址端口
local-address=0.0.0.0
local-port=54
#记录query 日志
query-logging=yes

启服务

systemctl start pnds

测试

通过api来访问

#需要带上配置文件中设置的api-key
curl -v -H 'X-API-Key: dnsadmin1syn' http://10.0.0.10:8081/api/v1/servers
* About to connect() to 10.0.0.10 port 8081 (#0)
*   Trying 10.0.0.10...
* Connected to 10.0.0.10 (10.0.0.10) port 8081 (#0)
> GET /api/v1/servers HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 10.0.0.10:8081
> Accept: */*
> X-API-Key: dnsadmin1syn
> 
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
< Connection: close
< Content-Length: 250
< Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
< Content-Type: application/json
< Server: PowerDNS/4.1.14
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-Permitted-Cross-Domain-Policies: none
< X-Xss-Protection: 1; mode=block
< 
* Closing connection 0
[{"config_url": "/api/v1/servers/localhost/config{/config_setting}", "daemon_type": "authoritative", "id": "localhost", "type": "Server", "url": "/api/v1/servers/localhost", "version": "4.1.14", "zones_url": "/api/v1/servers/localhost/zones{/zone}"}]

部署powerdns-admin

用来通过web界面,来管理pdns

通过docker来部署

docker run -it --rm \
    -e SECRET_KEY='dnsadmin1syn' \#这里的key就是pdns配置文件中设置的api-key
    -v pda-data:/data \
    -p 9191:80 \
    ngoduykhanh/powerdns-admin:latest

然后直接访问http://[IP]:9191

然后注册用户,第一个注册的用户默认为管理员

进去之后,需要添加pdns的服务

连接成功的会在左边菜单栏显示PDNS,没配置成功的是无法显示的

新建域名。创建一条记录

然后测试是否生效

dig www.abc.com @10.0.0.10 -p 54

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7 <<>> www.abc.com @10.0.0.10 -p 54
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38613
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1680
;; QUESTION SECTION:
;www.abc.com.			IN	A

;; ANSWER SECTION:
www.abc.com.		60	IN	A	1.1.1.1

;; Query time: 0 msec
;; SERVER: 10.0.0.10#54(10.0.0.10)
;; WHEN: 一 4月 24 12:10:54 CST 2023
;; MSG SIZE  rcvd: 56

已经可以正常解析

但是发现无法递归解析

这里以解析百度为例

dig www.baidu.com @10.0.0.10 -p 54

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7 <<>> www.baidu.com @10.0.0.10 -p 54
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 29256
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1680
;; QUESTION SECTION:
;www.baidu.com.			IN	A

;; Query time: 2 msec
;; SERVER: 10.0.0.10#54(10.0.0.10)
;; WHEN: 一 4月 24 12:12:02 CST 2023
;; MSG SIZE  rcvd: 42

可以看到是被拒绝的,这是因为,pdns服务是不提供递归和转发的,如果需要有递归和转发的功能,就需要启 pdns-recursor 服务

部署pdns-recursor递归服务

安装

yum install -y pdns-recursor

修改配置文件

vim /etc/pdns-recursor/recursor.conf
#允许访问的地址
allow-from=0.0.0.0/0
#开启日志
disable-syslog=yes
#关闭dnssec 转发有用
dnssec=off
#forward-zones是只转发,不递归 少用
#forward-zones=hexug.com=127.0.0.1:54
#forward-zones-recurse是找不到就递归,找的到就转发,用逗号分隔  这里是将pdns中定义的域名,转发到pdns服务的54端口上
forward-zones-recurse=hexug.com=127.0.0.1:54,abc.com=127.0.0.1:54,.=114.114.114.114
#绑定在所有端口商
local-address=0.0.0.0
local-port=53
log-common-errors=yes
security-poll-suffix=
setgid=pdns-recursor
setuid=pdns-recursor

启服务

systemctl restart pdns-recursor

注意,这里可能会报错,因为一般本地会有服务在占用53端口,需要先kill掉

再解析测试,这个时候解析的端口就不再是54端口,而是53端口

解析本地定义的域名

dig www.abc.com @10.0.0.10 -p 53

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7 <<>> www.abc.com @10.0.0.10 -p 53
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49462
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.abc.com.			IN	A

;; ANSWER SECTION:
www.abc.com.		52	IN	A	1.1.1.1

;; Query time: 0 msec
;; SERVER: 10.0.0.10#53(10.0.0.10)
;; WHEN: 一 4月 24 12:21:10 CST 2023
;; MSG SIZE  rcvd: 56

解析其他互联网域名

dig www.baidu.com @10.0.0.10 -p 53

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7 <<>> www.baidu.com @10.0.0.10 -p 53
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52182
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.baidu.com.			IN	A

;; ANSWER SECTION:
www.baidu.com.		125	IN	CNAME	www.a.shifen.com.
www.a.shifen.com.	125	IN	A	14.119.104.254
www.a.shifen.com.	125	IN	A	14.119.104.189

;; Query time: 28 msec
;; SERVER: 10.0.0.10#53(10.0.0.10)
;; WHEN: 一 4月 24 12:22:03 CST 2023
;; MSG SIZE  rcvd: 101

就可以正常解析

其他ui管理pdns

处理上面用容器部署的powerdns-admin容器服务

还有基于LNMP的powerdnsadmin服务,这里的唯一麻烦的点就是需要部署LNMP

可以借助 一键LNMP脚本

需要注意的是PHP版本一定要大于8.1

下载包 https://www.poweradmin.org/

解压到nginx的html文件中,然后访问 http://[IP][:port]/install 就可以安装