Help us understand the problem. What is going on with this article?

久しぶりにPowerDNSをさわる

More than 3 years have passed since last update.

どーも、hondam です。

なんでこのネタにしたかっていうと(ネタを考える時間が1日しかなかったのでやっつけなんて言えない)、最近よく社内でBIND祭があるのと、過去(3年前)に自分が書いた「[DNS] PowerDNSとAtomia DNSを使ってみる」という投稿が意外?と読まれているようなので、そういえばPowerDNSって最近どうしてるんだろう、息してるのかな?と思ったからです。

:repeat: PowerDNSおさらい

PowerDNSはGPLライセンスのC++で実装されたDNSサーバです。ほとんどのUNIXライクなOS上で動作します。PowerDNSはシンプルなBINDスタイルのゾーンファイルからRDBMSやロードバランシング/フェイルオーバーアルゴリズムまで多岐に渡る特徴があります。別プログラムとしてDNS recursorも含みます。

PowerDNSはオランダの企業PowerDNS.COM BVとオープンソースコミュニからの多くの貢献によって生み出されました。著名なデベロッパはBer Hubert氏です。

:date: 2013年からのバージョンアップ

3年前に使ってたバージョンはAuthoritative Serverの3.2です。そこからのバージョンアップ履歴ですが、SAやCVEでのアップデートがBINDと比べると断然少ないですね。あまり使われてない?という見方もありますが...祭りは少ない。

  • 4.0.1 2016年7月29日 CVE-2016-6172.
  • 4.0.0 2016年7月11日 ... ALIASレコード対応
  • 3.4.9 2016年5月17日
  • 3.4.8 2016年2月3日
  • 3.4.7 2015年11月3日 Security Advisory 2015-03
  • 3.4.6 2015年8月28日 Security Advisory 2015-02
  • 3.4.5 2015年6月9日 Security Advisory 2015-01
  • 3.4.4 2015年4月23日 Security Advisory 2015-01
  • 3.4.3 2015年3月2日
  • 3.4.2 2015年2月3日
  • 3.4.1 2014年10月30日
  • 3.4.0 2014年9月30日 ... REST API対応
  • 3.3.1 2013年12月17日
  • 3.3 2013年7月5日

:pencil: とりあえずインストール

インストールする環境は以下となります。たまには他のサービスを使ってみようかなということで某VPS(の月900円くらいの)にしました。

# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)

# cat /proc/version
Linux version 3.10.0-327.10.1.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC) ) #1 SMP Tue Feb 16 17:03:50 UTC 2016

ではインストール。バックエンドDBはとりあえずMySQLでいきます。
PowerDNSのインストールマニュアルは公式に用意されていますが、DBのインストール方法までは記載されていません。

# yum install mariadb mariadb-server

〜中略〜

インストール:
  mariadb.x86_64 1:5.5.50-1.el7_2
  mariadb-server.x86_64 1:5.5.50-1.el7_2

完了しました!

必要あれば /etc/my.cnf など修正してください。

# vi /etc/my.cnf
[mysqld]
character-set-server=utf8 # 追加するとか

systemctlでMySQLを有効にしておきます。

# systemctl list-unit-files --type=service | grep mariadb
mariadb.service                             disabled
# systemctl enable mariadb.service
# systemctl start mariadb.service

# ps xa | grep mysql
19272 ?        Ss     0:00 /bin/sh /usr/bin/mysqld_safe --basedir=/usr
19441 ?        Sl     0:00 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/var/log/mariadb/mariadb.log --pid-file=/var/run/mariadb/mariadb.pid --socket=/var/lib/mysql/mysql.sock

インストールの仕上げに mysql_secure_installation を実行しておきます。
このコマンドはrootユーザのパスワード変更や、anonymousユーザーの削除などを行うものなので、特に実行しなくてもOKです。実行した場合は適宜設定してください。

# mysql_secure_installation
OTE: 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):

〜中略〜

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

Thanks for using MariaDB!

mysql_secure_installationでrootユーザのパスワードを変更したので、接続可能か確認します。

# mysql -u root -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 11
Server version: 5.5.50-MariaDB MariaDB Server

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

OKですね。ではこの段階でPowerDNS用のデータベースとテーブルを作成しておきましょ。
まずはデータベースを作成します。ここでは pdns とします。

# mysql -u root -p  -e "CREATE DATABASE pdns CHARACTER SET utf8;"

次にPowerDNS用のテーブルを作成します。

# vi pdns_tables.sql
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                    INT 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);

先ほど作成したpdnsデータベースにインポートします。

# mysql -u root -p -D pdns < pdns_tables.sql

これでMySQLの準備はOKですね。
では次にPowerDNSをインストールします。

# yum info pdns
読み込んだプラグイン:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * base: ftp.iij.ad.jp
 * epel: ftp.riken.jp
 * epel-debuginfo: ftp.riken.jp
 * epel-source: ftp.riken.jp
 * extras: ftp.iij.ad.jp
 * updates: ftp.iij.ad.jp
利用可能なパッケージ
名前                : pdns
アーキテクチャー    : x86_64
バージョン          : 3.4.10
リリース            : 1.el7
容量                : 2.1 M
リポジトリー        : epel/x86_64
要約                : A modern, advanced and high performance authoritative-only nameserver
URL                 : http://powerdns.com
ライセンス          : GPLv2
説明                : The PowerDNS Nameserver is a modern, advanced and high performance
                    : authoritative-only nameserver. It is written from scratch and conforms
                    : to all relevant DNS standards documents.
                    : Furthermore, PowerDNS interfaces with almost any database.

3年前のバージョンは3.2でしたが、3.4.10になっているようです。

# yum install pdns pdns-backend-mysql

〜中略〜

インストール:
  pdns.x86_64 0:3.4.10-1.el7
  pdns-backend-mysql.x86_64 0:3.4.10-1.el7

完了しました!

次に pdns.conf を修正します。
デフォルトではMySQLを使うようになっていません。

# egrep -v '^\s*(#|$)' /etc/pdns/pdns.conf
setuid=pdns
setgid=pdns
launch=bind

MySQLのユーザやパスワードは適宜変更してください。ここではrootで設定しています。

# vi /etc/pdns/pdns.conf
setuid=pdns
setgid=pdns
launch=gmysql
gmysql-host=127.0.0.1
gmysql-user=root
gmysql-dbname=pdns
gmysql-password=[設定したパスワード]
# systemctl list-unit-files --type=service | grep pdns
pdns.service                             disabled
# systemctl enable pdns.service
# systemctl start pdns.service

ちなみに pdns.service の中身はこんな感じですね。

# cat /etc/systemd/system/multi-user.target.wants/pdns.service
[Unit]
Description=PowerDNS Authoritative Server
Wants=network-online.target
After=network-online.target mariadb.service postgresql.service slapd.service

[Service]
Type=forking
ExecStart=/usr/sbin/pdns_server --daemon
ExecStop=/usr/bin/pdns_control quit
Restart=on-failure
RestartSec=2
PrivateTmp=true

[Install]
WantedBy=multi-user.target

ではPowerDNSを起動したところで、名前解決できるかどうか確認してみましょ。

# dig +short www.example.com @127.0.0.1

当然結果は何も返ってきませんね。
ではテストのゾーン情報を登録してみます。

# vi example.com.zone.sql
INSERT INTO domains (name, type) values ('example.com', 'NATIVE');
INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'example.com','localhost ahu@ds9a.nl 1','SOA',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'example.com','dns-us1.powerdns.net','NS',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'example.com','dns-eu1.powerdns.net','NS',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'www.example.com','192.0.2.10','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'mail.example.com','192.0.2.12','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'localhost.example.com','127.0.0.1','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'example.com','mail.example.com','MX',120,25);

# mysql -u root -p -D pdns < example.com.zone.sql

おもむろに再実行すると...

# dig +short www.example.com @127.0.0.1
192.0.2.10

# dig +short example.com MX @127.0.0.1
25 mail.example.com.

OKですね。これでひとまずMySQLを使ってPowerDNSが動く状況になりました。
3年前の記事ではここからAtomia DNSをインストールしましたが、はたして状況は変わってるでしょうか。

PowerDNS向けのツールは、PowerDNSのAPIを呼び出すものと、SQL実行するものがあります。
以下はその一覧です。GitHubのPowerDNSのWikiに記載がありましたので載せておきます。
Atomia DNSも更新はあるようですね。

PowerDNSのAPIを利用するタイプ

名称 使用言語 更新履歴
nsedit PHP/JS Active
PowerDNS-Admin Python/JS Active
PowerDNS-Shell-Wrapper
(API based command-line tool)
Shell/Curl/JQ Active
pdnscontrol Python/JS Latest Commit 2016-03-30
yapdnsui express.js Latest Commit 2016-02-12
PoweREST React.js Latest Commit 2015-05-31
powr AngularJS Latest Commit 2015-02-15

SQLを利用するタイプ

名称 使用言語 更新履歴
django-powerdns-manager Django Active, Work in progress
DnsShop PHP/JS Active, code is since 2011 in production
NicTool Perl Active
PDNS Manager PHP Active
Poweradmin PHP Active
atomiadns JS Active
PowerDNS on Rails Ruby on Rails Last Commit 2015-09-30
pdns-gui PHP Last Commit 2014-11-18, but apparently in active use
freshdns PHP, AJAX Last Commit 2014-06-13
Powerdns Tango Perl Last Commit 2014-05-21
JPower Admin Java Last Release 2014-02-12
pdnsui Ramaze Last Commit 2014-01-09
ZoneAdmin PHP Last Release 2013-10-07
GNUPanel PHP Last Release 2013-07-20
phpDNSAdmin PHP Last Release 2013-05-16
powerdns-webinterface PHP Last Commit 2013-05-14
PowerDNS Administration PHP Last Release 2013-03-22
DNS Master PHP, jQuery Released 2012-10-09
MoxieDNS ??? demo-url & project dead? (2012-05-15)
GOsa² PHP Last Release 2012-05-09
PDNSOps PHP Last Commit 2012-02-12
pdns-ror-admin Ruby on Rails First/Last Commit in 2007-06-01
TUPA PHP, AJAX Last Release 2006-03-16
djdns Django Last Commit in 2009
pdns-tools Python Last Commit in 2009
pdnsfront PHP Last Commit in 2008

色々ありますが、息してるのは少ないかな。Atomia DNSは無事なようです。

PowerDNS-Admin

今回チョイスしたのは PowerDNS-Admin です。
単純にGitHubのStarの数と見た目で選びました。

では動くかわかりませんが早速インストールしてみましょう。
pdns.conf に以下の設定を追加します。

# vi /etc/pdns/pdns.conf
experimental-json-interface=yes
experimental-api-key=[適宜keyを設定してください]
webserver=yes

この設定でPowerDNSのREST APIが有効になります。
ではAPIが有効か確認してみましょう。

# curl -s -H 'X-API-Key: experimental-api-keyの値' http://127.0.0.1:8081/servers/localhost/zones | jq "."
[
  {
    "id": "example.com.",
    "url": "/servers/localhost/zones/example.com.",
    "name": "example.com",
    "kind": "Native",
    "dnssec": false,
    "account": "",
    "masters": [],
    "serial": 1,
    "notified_serial": 0,
    "last_check": 0
  }
]

OKですね。
では次にPowerDNS-Admin用のデータベースを作成します。

# mysql -u root -p  -e "CREATE DATABASE powerdnsadmin CHARACTER SET utf8;"
# mysql -u root -p  -e "GRANT ALL PRIVILEGES ON powerdnsadmin.* TO powerdnsadmin@'%' IDENTIFIED BY '適宜設定してください';"

ではPowerDNS-Adminを起動します。
起動に伴い、必要なパッケージのインストールと、設定が必要なので行います。
環境によっては既にインストールされているものもあると思いますので、過不足あれば適宜インストールしてください。

PowerDNS-Admin は PythonのマイクロフレームワークFlaskを使用しています。

# python -V
Python 2.7.5
# yum install python-pip
# yum install mariadb-devel
# yum install gcc

# git clone https://github.com/ngoduykhanh/PowerDNS-Admin.git
# cd PowerDNS-Admin

mariadb-devel は MySQL-pythonで必要だったのでインストールしています。
gccはldap関連のモジュールをインストールするのに必要でした。(今回はLDAP認証使ってませんが)

# pip install --upgrade pip
# pip install virtualenv
# pip install MySQL-python
# virtualenv flask
# source ./flask/bin/activate
(flask)# pip install -r requirements.txt
(flask)# cp config_template.py config.py 

(flask)# vi config.py
# DATABASE CONFIG
SQLA_DB_USER = 'powerdnsadmin'
SQLA_DB_PASSWORD = '適宜設定してください'
SQLA_DB_HOST = '127.0.0.1'
SQLA_DB_NAME = 'powerdnsadmin'

# POWERDNS CONFIG
PDNS_STATS_URL = '適宜設定してください'
PDNS_API_KEY = '適宜設定してください'
PDNS_VERSION = '適宜設定してください'

config.pyのデフォルトポートが9393だったので、firewall-cmdで9393ポートを開けました。
最後に./run.pyすれば起動されます。

(flask)# ./create_db.py
(flask)# firewall-cmd --add-port=9393/tcp --zone=public
(flask)# ./run.py
ログイン画面
スクリーンショット 2016-11-30 15.54.57.png
ダッシュボード画面
スクリーンショット 2016-11-30 15.53.01.png
レコード編集画面
スクリーンショット 2016-11-30 16.17.19.png

ということで無事PowerDNS-Adminが起動できました。
最初にテストで登録したゾーン情報が閲覧・変更できますね。

まともに権威DNSとして利用するにはもっとちゃんとした設定やSlaveも必要ですが、簡単そうなのは伝わったかと思います。

:notebook: 久しぶりにさわったPowerDNSまとめ

  • 祭りは少ない(ただあまり使われてないという見方も)。BINDに疲れたら。
  • PowerDNSのインストールは簡単(バックエンドをDBにすると多少運用が面倒)
  • いつのまにかREST APIが使えるようになってたので夢は広がりそう
  • Atomia DNS以外にイケてそうなUIの管理ツールも誕生してる

ということで12月1日担当の hondam でした。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away