PowerDNS 架設

BUBU 因為公司沒有內部用的 DNS 主機,所以需要新增一個 DNS 主機來架設給內部使用,找了一套適合並且又有網頁版的介面來操作,雖然沒有中文化。那目前我所設架的環境是 CentOS 7 下執行,版本是 PowerDNS 4.2版本。

網頁服務


安裝 nginx 服務

yum install nginx -y

資料庫


  • BUBU 是採用 MariaDB 10.3 版本,來進行安裝
新增加MariaDB安裝檔
vim /etc/yum.repos.d/MariaDB.repo

再填入內容為以下

# MariaDB 10.3 CentOS repository list - created 2018-08-20 14:44 UTC
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.3/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

增加完畢後在下命令安裝

yum install MariaDB-server MariaDB-client -y
  • 設定資料庫
systemctl restart mariadb.service ; systemctl enable mariadb.service # 啟動資料庫服
mysql_secure_installation   # 設定資料庫的root密碼

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): 第一次設定,直接按 Enter 鍵即可
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n] 按 Y 設定資料庫 root 密碼
New password: 輸入新密碼
Re-enter new password: 再次輸入新密碼
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] 按 Y 移除anonymous users
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] 按 Y 關閉 root 遠端登入
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] 按 Y 移除資料表 test
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] 按 Y 重新載入資料表權限
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!
  • 設定 PowerDNS 權限
mysql -u root -p   # 登入資料庫裡設定資表及權限

CREATE DATABASE powerdns CHARACTER SET utf8 COLLATE utf8_general_ci;

GRANT ALL ON powerdns.* TO 'powerdns'@'localhost' IDENTIFIED BY 'powerdns-password';

FLUSH PRIVILEGES;

增加 PowerDNS 必要的表單及欄位 4.2版本


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 UNSIGNED DEFAULT NULL,
  account               VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL,
  PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';

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               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,
  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);

開始安裝 PowerDNS 服務


官方各系統的 套件載點 BUBU 是使用 Cetnos 7 系統為服務,當下安裝的版本為 PowerDNS 4.2

PowerDNS Authoritative Server - version 4.2

yum install epel-release yum-plugin-priorities -y &&
curl -o /etc/yum.repos.d/powerdns-auth-42.repo https://repo.powerdns.com/repo-files/centos-auth-42.repo &&
yum install pdns pdns-backend-mysql -y
PowerDNS Recursor - version 4.2

yum install epel-release yum-plugin-priorities &&
curl -o /etc/yum.repos.d/powerdns-rec-42.repo https://repo.powerdns.com/repo-files/centos-rec-42.repo &&
yum install pdns-recursor -y
Metronome - master branch

yum install epel-release yum-plugin-priorities &&
curl -o /etc/yum.repos.d/powerdns-metronome-master.repo https://repo.powerdns.com/repo-files/centos-metronome-master.repo &&
yum install metronome -y
dnsdist - version 1.4

yum install epel-release yum-plugin-priorities &&
curl -o /etc/yum.repos.d/powerdns-dnsdist-14.repo https://repo.powerdns.com/repo-files/centos-dnsdist-14.repo &&
yum install dnsdist -y
  • 服務都安裝完之後開始設定兩個設定檔

PowerDNS 設定檔(Master)


  • 備份預設檔,建立新的設定檔
mv /etc/pdns/pdns.conf /etc/pdns/pdns.conf.bak
vim /etc/pdns/pdns.conf
  • 以下是我比較會異動到的設定檔,如果還要增加設定,請參考預設檔複製過來即可
#################################
# api	Enable/disable the REST API (including HTTP listener)
#
# api=no
api=yes

#################################
# api-key	Static pre-shared authentication key for access to the REST API
#
# api-key=
api-key=自行定義密碼

#################################
# daemon	Operate as a daemon
#
daemon=yes

#################################
# guardian	Run within a guardian process
#
guardian=no

#################################
# launch	Which backends to launch and order to query them in
#
# launch=\nlaunch=
#
launch=gmysql
gmysql-host=localhost
gmysql-user=powerdns
gmysql-password=powerdns-password
gmysql-dbname=powerdns
gmysql-dnssec=yes

#################################
# local-address	Local IP addresses to which we bind
#
# local-address=0.0.0.0
local-address=0.0.0.0

#################################
# local-port	The port on which we listen
#
# local-port=53
local-port=54

#################################
# log-dns-details	If PDNS should log DNS non-erroneous details
#
# log-dns-details=no
log-dns-details=yes

#################################
# log-dns-queries	If PDNS should log all incoming DNS queries
#
# log-dns-queries=no
log-dns-queries=yes

#################################
# log-timestamp	Print timestamps in log lines
#
# log-timestamp=yes
log-timestamp=yes

#################################
# logging-facility      Facility to log messages as. 0 corresponds to local0
#
# logging-facility=
logging-facility=0

#################################
# loglevel	Amount of logging. Higher is more. Do not set below 3
#
# loglevel=4
loglevel=4

#################################
# master        Act as a master
#
# master=no
master=yes

#################################
# setgid        If set, change group id to this gid for more security
#
setgid=pdns

#################################
# setuid        If set, change user id to this uid for more security
#
setuid=pdns

#################################
# webserver	Start a webserver for monitoring (api=yes also enables the HTTP listener)
#
# webserver=no
webserver=yes

#################################
# query-logging Hint backends that queries should be logged
#
# query-logging=no
query-logging=yes
  • 設定自動啟動及重啟 PowerDNS 服務
systemctl enable pdns.service ; systemctl restart  pdns.service

PowerDNS 設定檔 (Slave)


  • 備份預設檔,建立新的設定檔
mv /etc/pdns/pdns.conf /etc/pdns/pdns.conf.bak
vim /etc/pdns/pdns.conf
  • 以下是我比較會異動到的設定檔,如果還要增加設定,請參考預設檔複製過來即可
#################################
# api	Enable/disable the REST API (including HTTP listener)
#
# api=no
api=yes

#################################
# api-key	Static pre-shared authentication key for access to the REST API
#
# api-key=
api-key=自行定義密碼

#################################
# daemon	Operate as a daemon
#
daemon=yes

#################################
# guardian	Run within a guardian process
#
guardian=no

#################################
# launch	Which backends to launch and order to query them in
#
# launch=\nlaunch=
#
launch=gmysql
gmysql-host=localhost
gmysql-user=powerdns
gmysql-password=powerdns-password
gmysql-dbname=powerdns
gmysql-dnssec=yes

#################################
# local-address	Local IP addresses to which we bind
#
# local-address=0.0.0.0
local-address=0.0.0.0

#################################
# local-port	The port on which we listen
#
# local-port=53
local-port=54

#################################
# log-dns-details	If PDNS should log DNS non-erroneous details
#
# log-dns-details=no
log-dns-details=yes

#################################
# log-dns-queries	If PDNS should log all incoming DNS queries
#
# log-dns-queries=no
log-dns-queries=yes

#################################
# log-timestamp	Print timestamps in log lines
#
# log-timestamp=yes
log-timestamp=yes

#################################
# logging-facility      Facility to log messages as. 0 corresponds to local0
#
# logging-facility=
logging-facility=0

#################################
# loglevel	Amount of logging. Higher is more. Do not set below 3
#
# loglevel=4
loglevel=4

#################################
# slave Act as a slave
#
# slave=no
slave=yes

#################################
# slave-cycle-interval  Schedule slave freshness checks once every .. seconds
#
# slave-cycle-interval=60
slave-cycle-interval=60

#################################
# setgid        If set, change group id to this gid for more security
#
setgid=pdns

#################################
# setuid        If set, change user id to this uid for more security
#
setuid=pdns

#################################
# webserver	Start a webserver for monitoring (api=yes also enables the HTTP listener)
#
# webserver=no
webserver=yes

#################################
# query-logging Hint backends that queries should be logged
#
# query-logging=no
query-logging=yes
  • 設定自動啟動及重啟 PowerDNS 服務
systemctl enable pdns.service ; systemctl restart  pdns.service

PowerDNS Recursor 設定檔 這是負責遞迥查詢服務


  • 備份預設檔,建立新的設定檔
mv /etc/pdns-recursor/recursor.conf /etc/pdns-recursor/recursor.conf.bak
vim /etc/pdns-recursor/recursor.conf
  • 以下是我比較會異動到的設定檔,如果還要增加設定,請參考預設檔複製過來即可
#################################
# allow-from	If set, only allow these comma separated netmasks to recurse
#
# allow-from=127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fc00::/7, fe80::/10
allow-from=127.0.0.1, 192.168.0.0/24  #設定允許遞迥查詢內部網段

#################################
# forward-zones	Zones for which we forward queries, comma separated domain=ip pairs
#
# forward-zones=
forward-zones=.=127.0.0.1:54  #轉送查詢的網域與伺服器,格式是 網域=伺服器ip,多個網域以逗點分隔

#################################
# forward-zones-recurse Zones for which we forward queries with recursion bit, comma separated domain=ip pairs
#
# forward-zones-recurse=
forward-zones-recurse=.=8.8.8.8, .=168.95.1.1 #內部查詢不到會查到外部查詢

#################################
# local-address	IP addresses to listen on, separated by spaces or commas. Also accepts ports.
#
# local-address=127.0.0.1
local-address=0.0.0.0

#################################
# local-port	port to listen on
#
# local-port=53
local-port=53

#################################
# logging-facility      Facility to log messages as. 0 corresponds to local0
#
# logging-facility=
logging-facility=0

#################################
# max-negative-ttl      maximum number of seconds to keep a negative cached entry in memory
#
# max-negative-ttl=3600
max-negative-ttl=3600

#################################
# setgid        If set, change group id to this gid for more security
#
setgid=pdns-recursor

#################################
# setuid        If set, change user id to this uid for more security
#
setuid=pdns-recursor
  • 設定自動啟動及重啟 PowerDNS-Recursor 服務
啟動服務
systemctl start pdns-recursor ; systemctl enable pdns-recursor

PowerDNS-Admin 服務設定


  • 安裝 Python 版,必要套件
yum update -y
yum install yum-utils -y
yum groupinstall development -y

安裝 IUM 套件庫
yum install \
https://repo.ius.io/ius-release-el7.rpm \
https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

開始安裝 Python 3.6
yum install python36u python36u-pip python36u-devel -y
pip3.6 install -U pip
pip install -U virtualenv
rm -f /usr/bin/python3 && ln -s /usr/bin/python3.6 /usr/bin/python3
  • 安裝 requirements.txt 構建 Pythone 套件
If you use MariaDB ( from MariaDB "upstream" repositorys (10.x) )
yum install gcc MariaDB-devel MariaDB-shared openldap-devel xmlsec1-devel xmlsec1-openssl libtool-ltdl-devel -y
  • 安裝 yarn
curl -sL https://rpm.nodesource.com/setup_10.x | bash -
curl -sL https://dl.yarnpkg.com/rpm/yarn.repo -o /etc/yum.repos.d/yarn.repo
yum install yarn -y

安裝 PowerDNS-Admin


  • 設定 PowerDNS 的 API
api=yes
api-key=your-powerdns-api-key
webserver=yes
  • PowerDNS-Admin 建立資料庫
CREATE DATABASE powerdnsadmin CHARACTER SET utf8 COLLATE utf8_general_ci;
GRANT ALL PRIVILEGES ON powerdnsadmin.* TO 'pdnsadminuser'@'%' IDENTIFIED BY 'p4ssw0rd';
FLUSH PRIVILEGES;
quit;
  • 安裝 PowerDNS-Admin
git clone https://github.com/ngoduykhanh/PowerDNS-Admin.git /opt/web/powerdns-admin
cd /opt/web/powerdns-admin
virtualenv -p python3 flask
  • 進入 Python 模式並且開始安裝
. ./flask/bin/activate
(flask) [[email protected] powerdns-admin] pip install python-dotenv
(flask) [[email protected] powerdns-admin] pip install -r requirements.txt
  • 安裝完之後設定 PowerDNS-Admin 設定檔
vim /opt/web/powerdns-admin/powerdnsadmin/default_config.py
  • 修改設定檔如下
SECRET_KEY = 'We are the world' 在瀏覽器中對cookie進行簽名
BIND_ADDRESS = '127.0.0.1' 修改成 0.0.0.0 允許所有可以連線
PORT = 9191

SQLA_DB_USER = 'pdnsadminuser'
SQLA_DB_PASSWORD = 'powerdns-password'
SQLA_DB_HOST = '127.0.0.1'
SQLA_DB_PORT = 3306
SQLA_DB_NAME = 'powerdnsadmin'
SQLALCHEMY_TRACK_MODIFICATIONS = True

設定完存檔,並且開始安裝服務

  • 運行下面指令自動建立 PowerDNS-Admin 資料庫裡的表單及欄位
(flask) [[email protected] powerdns-admin] export FLASK_APP=powerdnsadmin/__init__.py
(flask) [[email protected] powerdns-admin] flask db upgrade
  • 產生資料檔
(flask) [[email protected] powerdns-admin] yarn install --pure-lockfile
(flask) [[email protected] powerdns-admin] flask assets build
  • 運行 PowerDNS-Admin 服務
(flask) [[email protected] powerdns-admin] ./run.py
  • 安裝完之後開始瀏灠器輸入 http://dns主機ip:9191 如果看到登入畫面表示您已安裝成功了可以使用了

dns-1.png

  • 剛安裝完成官方並沒有預計任何的帳號,所以需要手動自行去建立帳號跟密碼輸入完之後就可以登入了

dns-2.png

  • 登入後會看到此頁面,要開輸入跟 PowerDNS 連接的 API

    • API :http://127.0.0.1:8081
    • API-kye:輸入當時所設定的密碼
    • PDNS:輸入當時安裝的版本
    • PowerDNS 版本查詢: pdns_control version
  • 設定完之後按下 Update 就可以了

dns-3.png

  • 如果設定成功的話在 PDNS 選項裡面就可以看到 PDNS 目前設定狀況,如圖下

DNS7.png

  • 如果設定失敗的話,有可能是 api 的資訊有誤,跟版本或者密碼輸入有訊,如圖下是失敗的畫面,沒有連線成功的話後面新增網域的設定會有問題的。

DNS6.png

  • 再來進到設定裡面把預設可以讓使用者註冊給取消掉,把 Allow users to sign up 這個打勾給拿掉就可以了

dns-4.png

108.12.23 以下這一段,照著官方的設定還是有問題,目前已有人提出問題,目前正在等待官方的回應。
109.01.03 官方是用 pdns 權限執行,修改成 root 就可以正常運行了

但是這樣子使用上並不方便,服務都需要手動去啟用,所以官方建議還需要寫個服務來啟用,並且搭配網頁服務來使用。

  • 新增 powerdns-admin 服務設定檔 vim /etc/systemd/system/powerdns-admin.service
[Unit]
Description=PowerDNS-Admin
Requires=powerdns-admin.socket
After=network.target

[Service]
PIDFile=/run/powerdns-admin/pid
User=root
Group=root
WorkingDirectory=/opt/web/powerdns-admin
ExecStart=/opt/web/powerdns-admin/flask/bin/gunicorn --pid /run/powerdns-admin/pid --bind unix:/run/powerdns-admin/socket 'powerdnsadmin:create_app()'
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
  • 新增 powerdns-admin.socket 設定檔 vim /etc/systemd/system/powerdns-admin.socket
[Unit]
Description=PowerDNS-Admin socket

[Socket]
ListenStream=/run/powerdns-admin/socket

[Install]
WantedBy=sockets.target
  • 新增 powerdns-admin.conf 設定檔 vim /etc/tmpfiles.d/powerdns-admin.conf
d /run/powerdns-admin 0755 root root -
  • 啟動服務
systemctl daemon-reload; sudo systemctl start powerdns-admin.socket; sudo systemctl enable powerdns-admin.socket
  • Nginx 設定檔
server {
  listen *:80;
  server_name               powerdns-admin.local www.powerdns-admin.local;

  index                     index.html index.htm index.php;
  root                      /opt/web/powerdns-admin;
  access_log                /var/log/nginx/powerdns-admin.local.access.log combined;
  error_log                 /var/log/nginx/powerdns-admin.local.error.log;

  client_max_body_size              10m;
  client_body_buffer_size           128k;
  proxy_redirect                    off;
  proxy_connect_timeout             90;
  proxy_send_timeout                90;
  proxy_read_timeout                90;
  proxy_buffers                     32 4k;
  proxy_buffer_size                 8k;
  proxy_set_header                  Host $host;
  proxy_set_header                  X-Real-IP $remote_addr;
  proxy_set_header                  X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_headers_hash_bucket_size    64;

  location ~ ^/static/  {
    include  /etc/nginx/mime.types;
    root /opt/web/powerdns-admin/powerdnsadmin;

    location ~*  \.(jpg|jpeg|png|gif)$ {
      expires 365d;
    }

    location ~* ^.+.(css|js)$ {
      expires 7d;
    }
  }

  location / {
    proxy_pass            http://unix:/run/powerdns-admin/socket;
    proxy_read_timeout    120;
    proxy_connect_timeout 120;
    proxy_redirect        off;
  }

}

PowerDNS Log 記錄


因官方預設是關閉的,所要手動去啟用

systemctl edit --full pdns

看到 ExecStart 這一行將裡面的 --disable-syslog 刪除掉

去到 vim /etc/rsyslog.conf 增加給 PowerDNS 使用
local0.info                       -/var/log/pdns.info
local0.warn                       -/var/log/pdns.warn
local0.err                        /var/log/pdns.err

再去將 pdns.conf 及 recursor.conf 這兩個設定檔
修變這一行 logging-facility=0

以上修改完之後整個系統都重啟,就可以在 log 資料夾裡面看到這三個檔案

PowerDNS 支援 Active Directory 網域服務


PowerDNS 有支援動態更新 DNS 服務,在建置 AD 服務可以考慮將 DNS 設定指向 PowerDNS 服務來使用,修改 PowerDNS 配置文件使其支持动态更新。

vim /etc/pdns/pdns.conf

################################
# allow-dnsupdate-from  A global setting to allow DNS updates from these IP ranges.
#
# allow-dnsupdate-from=127.0.0.0/8,::1
allow-dnsupdate-from=127.0.0.0/8

#################################
# dnsupdate     Enable/Disable DNS update (RFC2136) support. Default is no.
#
# dnsupdate=no
dnsupdate=yes
  • 添加修改解析記錄
@	SOA	Active	3600	ns.adtest.com. ns.adtest.com. 2017112802 10800 3600 604800 3600 
_kerberos._tcp	SRV	Active	3600	0 0 88 ad.adtest.com. 
_kerberos._tcp.dc._msdcs	SRV	Active	3600	0 0 88 ad.adtest.com. 
_ldap._tcp	SRV	Active	3600	0 0 389 ad.adtest.com. 
_ldap._tcp.dc._msdcs	SRV	Active	3600	0 0 389 ad.adtest.com. 
ad	A	Active	3600	192.168.50.207 
ns	A	Active	3600	192.168.50.237
  • PowerDNS-Admin 允許通過 DynDNS 更新需創建記錄域名面板中,進入需要修改的域名 Admin 設定,在 DynDNS 2 Settings 勾選 Allow on-demand creation of records via DynDNS updates?



參考相關網頁




Q & A