phpIPAMを使ってIPアドレス管理を始めたい僕の二歩目

前回は `phpIPAMをインストールして動作概要を確認 <https://ainoniwa.net/pelican/2017/0717a.html>`_ しました。 これだけだと死活監視とオートディスカバリー機能付きのIPアドレスの管理簿がWebになっただけ。(あれ?これだけでも十分かな?) せっかくなので、登録したホストが実際のDNSに反映されて欲しいところです。 都合のいいことに、phpIPAMにはPowerDNSとの連携機能が搭載されているのです。 今回はPowerDNSを追加でインストールして、phpIPAMによるIPとDNSの管理の統合を目指してみます。

phpIPAMを使ってIPアドレス管理を始めたい僕の二歩目

PowerDNSのインストール

今回は 前回の手順 <https://ainoniwa.net/pelican/2017/0717a.html>_ の続きとなります。

CentOS 7.3の場合、PowerDNSのインストールは、EPELと専用のリポジトリを使ってインストールします。

手順: https://repo.powerdns.com/

1
2
3
sudo yum install -y epel-release yum-plugin-priorities
sudo curl -o /etc/yum.repos.d/powerdns-auth-40.repo https://repo.powerdns.com/repo-files/centos-auth-40.repo
sudo yum install -y pdns-backend-mysql

PowerDNSの初期設定

まずはPowerDNS用のデータベースとユーザーを作ります。

mysql -u root -p でログインして以下のコマンドを叩きます。

1
2
3
4
5
CREATE DATABASE pdns CHARACTER SET utf8;
CREATE USER 'pdns'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON pdns.* TO 'pdns'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON pdns.* TO 'pdns'@'localhost' IDENTIFIED BY 'password';
quit

PowerDNSのバックエンド設定をMariaDB(MySQL)に変更します。

これは差分ですけど、こんな感じで編集してください。

1
2
3
4
5
6
# sdiff -s /etc/pdns/pdns.conf /etc/pdns/pdns.conf.org 
launch=gmysql                                                 | launch=
gmysql-host=127.0.0.1                                         <
gmysql-user=pdns                                              <
gmysql-dbname=pdns                                            <
gmysql-password=password                                      <

mysql -u pdns -p でログインして、PowerDNSのレコード管理テーブルを作ります。
実行すべきSQLはPowerDNSのドキュメントに書いてあります。 <https://doc.powerdns.com/md/authoritative/howtos/#basic-setup-configuring-database-connectivity>_

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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(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);

PowerDNSの起動

Firewallの設定とサービスの起動をします。

1
2
3
sudo firewall-cmd --permanent --add-service=dns
sudo firewall-cmd --reload
sudo systemctl start pdns

phpIPAMとPowerDNSの連携

phpipamはPowerDNSのDBテーブルへ直接アクセスしようとするので、httpdからDBへのSELinuxのアクセス許可が必要になります。

1
sudo setsebool -P httpd_can_network_connect_db on

次に、phpIPAMのGUIから以下の設定を追加します。

まずはPowerDNSのプラグインを有効にします。

Administration -> phpIPAM settings -> Power DNS -> ON を設定して保存します。(下図赤丸部)

Administration -> PowerDNS から設定画面へ。最初は接続できていないのでエラーが出ています。

PowerDNSで使用しているDBの接続情報を入力して保存します。

DBへ接続が成功したら、ドメインが作成できるようになります。

まずは default powerDNS values からレコード登録時のデフォルト値を設定します。

こんな感じでしょうか。

.. warning::

Hostmasterは(BINDの表記に慣れてると)ピンとこないんですが、どうやらソースコードを読んだ感じ *validate_email* と書かれていたので、普通にメールアドレスの表記で入力します。

それでは、試しにドメインを作成してアクセスを確認してみましょう。

“Domains” から “+ Create domain” を選択して、ドメイン情報を入力します。

同様に “Reverse V4” から逆引きゾーンの登録をします。

ここまで設定したら、前回設定したサブネット画面に移動します。

すると、前回は無かった “+” ボタンが増えています。(下図赤丸部)

その “+” ボタンを押すと、レコードの登録画面が出るので、Aレコードの場合はそのまま “+ Add” ボタンを押せば、レコードが登録されます。

動作確認

PowerDNSのレコード登録を確認します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ mysql -updns -ppassword -e 'select * from pdns.records;'
+----+-----------+---------------------+------+--------------------------------------------------------------+------+------+-------------+----------+-----------+------+
| id | domain_id | name                | type | content                                                      | ttl  | prio | change_date | disabled | ordername | auth |
+----+-----------+---------------------+------+--------------------------------------------------------------+------+------+-------------+----------+-----------+------+
|  1 |         1 | example.com         | SOA  | ns01.example.com root.example.com 2017071903 3600 600 600 60 | 3600 | NULL |  2017071903 |        0 | NULL      |    1 |
|  2 |         1 | example.com         | NS   | ns01.example.com                                             | 3600 | NULL |  2017071900 |        0 | NULL      |    1 |
|  3 |         2 | 0.0.10.in-addr.arpa | SOA  | ns01.example.com root.example.com 2017071902 3600 600 600 60 | 3600 | NULL |  2017071902 |        0 | NULL      |    1 |
|  4 |         2 | 0.0.10.in-addr.arpa | NS   | ns01.example.com                                             | 3600 | NULL |  2017071900 |        0 | NULL      |    1 |
|  5 |         1 | phpipam.example.com | A    | 10.0.0.131                                                   | 3600 | NULL |  2017071900 |        0 | NULL      |    1 |
+----+-----------+---------------------+------+--------------------------------------------------------------+------+------+-------------+----------+-----------+------+

digで引いてみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ dig @10.0.0.131 phpipam.example.com

; <<>> DiG 9.9.4-RedHat-9.9.4-50.el7_3.1 <<>> @10.0.0.131 phpipam.example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6038
;; 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:
;phpipam.example.com.           IN      A

;; ANSWER SECTION:
phpipam.example.com.    3600    IN      A       10.0.0.131

;; Query time: 2 msec
;; SERVER: 10.0.0.131#53(10.0.0.131)
;; WHEN: Wed Jul 19 00:09:55 JST 2017
;; MSG SIZE  rcvd: 64

この時点では逆引きが設定されていないので、更に逆引きの設定を追加します。

まずはサブネット設定を開いて “Autocreate reverse records” を “Yes” にしたら保存します。

次に “Autocreate reverse records” の更新ボタンを押します。(下図赤丸部)

そして “Regenerate” ボタンを押すと、逆引きレコードが生成されてDBに保存されます。

もう一度、PowerDNSのレコード登録を確認します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ mysql -updns -ppassword -e 'select * from pdns.records;'
+----+-----------+-------------------------+------+--------------------------------------------------------------+------+------+-------------+----------+-----------+------+
| id | domain_id | name                    | type | content                                                      | ttl  | prio | change_date | disabled | ordername | auth |
+----+-----------+-------------------------+------+--------------------------------------------------------------+------+------+-------------+----------+-----------+------+
|  1 |         1 | example.com             | SOA  | ns01.example.com root.example.com 2017071903 3600 600 600 60 | 3600 | NULL |  2017071903 |        0 | NULL      |    1 |
|  2 |         1 | example.com             | NS   | ns01.example.com                                             | 3600 | NULL |  2017071900 |        0 | NULL      |    1 |
|  3 |         2 | 0.0.10.in-addr.arpa     | SOA  | ns01.example.com root.example.com 2017071904 3600 600 600 60 | 3600 | NULL |  2017071904 |        0 | NULL      |    1 |
|  4 |         2 | 0.0.10.in-addr.arpa     | NS   | ns01.example.com                                             | 3600 | NULL |  2017071900 |        0 | NULL      |    1 |
|  5 |         1 | phpipam.example.com     | A    | 10.0.0.131                                                   | 3600 | NULL |  2017071900 |        0 | NULL      |    1 |
|  6 |         2 | 131.0.0.10.in-addr.arpa | PTR  | phpipam.example.com                                          | 3600 | NULL |  2017071900 |        0 | NULL      |    1 |
|  7 |         2 | 141.0.0.10.in-addr.arpa | PTR  | dev01.example.com                                            | 3600 | NULL |  2017071900 |        0 | NULL      |    1 |
+----+-----------+-------------------------+------+--------------------------------------------------------------+------+------+-------------+----------+-----------+------+

digで引いてみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ dig @10.0.0.131 -x 10.0.0.131

; <<>> DiG 9.9.4-RedHat-9.9.4-50.el7_3.1 <<>> @10.0.0.131 -x 10.0.0.131
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7184
;; 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:
;131.0.0.10.in-addr.arpa.       IN      PTR

;; ANSWER SECTION:
131.0.0.10.in-addr.arpa. 3600   IN      PTR     phpipam.example.com.

;; Query time: 2 msec
;; SERVER: 10.0.0.131#53(10.0.0.131)
;; WHEN: Wed Jul 19 00:39:38 JST 2017
;; MSG SIZE  rcvd: 85

これでAレコードとPTRレコードが登録されたことが確認できました。

今回はIPアドレスが登録済みだったので後から設定しましたが、PTRレコードはIPアドレスを登録した時点で自動的に登録されるため、今回のようにいちいち設定する必要はありません。(デフォルト動作)

逆に、Aレコードは自動的に登録されないので、個別に先ほどのホスト名の横に置かれた “+” ボタンから追加する必要があります。

それも自動的に登録されるようにすること自体は簡単にできそうなので、すぐに対応されると信じたいですね。

おしまい

これで、IPアドレスとホスト名の一元管理が出来るようになりました。
見栄えも良いので、小規模かつ変更が多い実験室環境では非常に有益ではないでしょうか。
理想的にはMACとIPアドレスの登録をDHCPとも組み合わせたいところですが、API制御ができるDHCPサーバーも限られているので、少し難しいでしょうか。

phpIPAMは確かにphp製だけど、PowerDNSのWeb管理画面だってphpなんだから丁度いい気がしてきますよね。
phpIPAMには他にも色々な機能があるので、試してみてはいかがでしょうか。

と言うわけで、今日はここまで。

Built with Hugo
テーマ StackJimmy によって設計されています。