😽

権威DNSをPowerDNS Authoritativeで、キャッシュDNSをRecursorで構築してみる

2020/09/29に公開1

内部DNS向けにDNSコンテンツサーバに PowerDNS Authoritative server を、また内部ドメイン・外部ドメインへの再帰問い合わせに対応させるため PowerDNS Recursor を構築してみた。

導入環境

  • CentOS Linux release 7.6.1810 (Core)
  • PowerDNS Authoritative Server 4.2
  • PowerDNS Recursor 4.2

構築

順番的には下記のような流れ。

  1. EPELとRemiレポジトリのインストール
  2. MariaDBのインストールと設定
  3. PowerDNSとRecursorのインストールと設定

レコード管理には PowerDNS-Admin などのツールがあるが、今回はDNS以外のものも管理したいので PHPIPAM を利用するためインストールしない。

EPELとRemiレポジトリのインストール

最初に、PowerDNSとその依存パッケージをインストールする。
EPEL と PowerDNS のリポジトリとREMI for PHP 7.2をインストール。

sudo yum -y install epel-release
sudo yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
sudo curl -o /etc/yum.repos.d/powerdns-auth-40.repo https://repo.powerdns.com/repo-files/centos-auth-40.repo

yum-utilsもインストールし、yum-config-managerでremiを有効にしておく。

sudo yum -y install yum-utils
sudo yum-config-manager --enable remi-php72

MariaDBのインストールと設定

PowerDNSのバックエンドDBにMySQLを利用するので、MariaDBをインストールし、初期設定を済ませる。

sudo yum -y install mariadb mariadb-server
sudo systemctl start mariadb
sudo systemctl enable mariadb

初期設定はmysql_secure_installationで行う。

sudo mysql_secure_installation

Set root password? [Y/n] Y
New password: <Password>
Re-enter new password: <Password>

Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y

MySQLへPowerDNS用のDBを作成する。

sudo mysql -u root -p <Password>
create database powerdns;
grant all privileges on powerdns.* to powerdns@localhost identified by 'powerdns';
flush privileges;

以下MySQLクエリを実行し、PowerDNSのテーブルを作成する。

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               VARCHAR(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               VARCHAR(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);

 quit;

上記のクエリを流し込むことでPowerDNSインストールの準備は完了。

PowerDNSとRecursorのインストールと設定

パッケージをまとめてインストール。

sudo yum -y install pdns pdns-backend-mysql bind-utils pdns-recursor

パッケージをインストール後、/etc/pdns/に移動し、設定ファイルpdns.confを編集する。
以下コンフィグ例。

allow-dnsupdate-from=0.0.0.0/0
api=yes
api-key=api-key
api-logfile=/var/log/powerdns/pdns.log

daemon=yes
dnsupdate=yes
guardian=yes

launch=gmysql
gmysql-host=localhost
gmysql-user=pdns
gmysql-password=powerdns
gmysql-dbname=powerdns

local-address=127.0.0.1
local-port=8053

disable-syslog=yes
log-dns-details=yes
log-timestamp=yes
logging-facility=0
loglevel=6

setgid=pdns
setuid=pdns

webserver=yes
webserver-address=127.0.0.1
webserver-port=8081

通常、コンテンツDNSだけであればlocal-port=はDNS標準の53番ポートを設定するといいが、キャッシュDNSである Recursor を同一サーバ上に構築しているため、ここではlocal-port=8053としている。

次に Recursor の設定。
以下例。

allow-from=127.0.0.0/8,10.10.0.0/16

config-dir=/etc/powerdns
etc-hosts-file=/etc/hosts
export-etc-hosts=on

forward-zones=knbash.com=127.0.0.1:8053, dev.knbash.com=10.10.0.1;10.10.0.2
forward-zones-recurse=.=8.8.8.8

hint-file=/usr/share/dns/root.hints

include-dir=/etc/powerdns/recursor.d

local-address=10.10.0.3
local-port=53

log-common-errors=yes
log-timestamp=yes
logging-facility=0
loglevel=6

security-poll-suffix=
setgid=pdns-recursor
setuid=pdns-recursor

前述の通り、local-port=53とすることで、クライアントからの要求は Recursor が受け取り、内容によって外部か内部か振り分けるようにする。

動作確認

PowerDNS関連の起動と自動起動の有効化し、FWの設定を実行。

sudo systemctl start pdns
sudo systemctl enable pdns
sudo systemctl start pdns-recursor
sudo systemctl enable pdns-recursor
sudo firewall-cmd --add-port=53/tcp --permanent
sudo firewall-cmd --add-port=53/udp --permanent
sudo firewall-cmd --add-port=8053/tcp --permanent
sudo firewall-cmd --add-port=8053/udp --permanent
sudo firewall-cmd --reload

あとはサーバ自身でdigなりnslookupで名前解決ができることを確認。
サーバで問題なければ、クライアント側でDNSサーバへ構築したサーバを指定して名前解決ができるか確認し、完了。

PowerDNS単体では、レコード登録をコマンドを実行して対応しなければいけないので、管理ソフトを入れると便利。

Discussion

SKMT.xxSKMT.xx

8053のポート許可って必須なのですかね。
127.0.0.1でlistenだから要らないような気がしました。