PowerDNS 通称 pdns が便利。
pdns が便利そう。なので使ってみてる。
Power DNS で出来ること
PowerDNSはDNSで出来ることが一通り全てできる。
- 権威サーバー
- ミラーサーバー
- キャッシュサーバー
これらをちゃんと実装している。
さらに、コンテンツサーバーについては、ゾーンとレコードをSQLバックエンドに放り込むことが出来る。
SQLでバックエンドに放り込めるだけでもすごいのに
- bind
- mydns
- tinydns
これらのファイル形式に対応してて、レコードを様々な形で持つことが出来る。いいな、これ。
あと、LDAPに格納したレコードも使えるらしい。無敵か。
さらにHTTP機能がある。
WEBサーバー機能があって、PowerDNSのモニタリングができて、HTTP APIまでもがついてくる。
インストールして使ってみる。
インストールに必要なものと、インストールした環境
こんかいはCentOSを引っ張り出してきた。
準備 : 1
DNS を扱うのでDNSを扱うのに必要な dig コマンドを用意しておく
sudo yum install bind-utils
dig いれたら準備段階として dig の結果とネットワーク疎通を見ておく
dig +short t.co
その他に bash-completion nmap vim-enhanced などを入れた
準備 : mysql をインストール
mysql サーバーにDNSレコードを作ることにするので、MySQLを準備してくる
sudo yum install mysql-community-server
mysql のroot の基本設定をしておく
sudo mysql_secure_installation
MySQLにユーザーとデータベースとテーブルを準備する。
MySQLをインストールしたので、ユーザーを作る
create user 'pdns'@'%' identified by 'password';
MySQL に pdns のデータベースを作る。
もう管理が面倒くさいのでユーザー名と同じにした。
create database pdns;
pdns ユーザーにデータベースの権限をGRANTする
grant all on pdns.* to 'pdns'@'%'
一通りがおわったら、flush しておく
flush privileges;
pdns ユーザーでログインしてみる
mysql -u pdns -p
ログインできたら権限をチェックしておく
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 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);
テーブル構造の詳細は公式ドキュメントにある。今回は、domains/zonesさえアレば動くので、これだけ持ってきておいた。
っていうか。テーブル構造は全然うるさくない。自分で適当なテーブルで作ってもいいし、名前をマッピングしておけばちゃんと動くらしい。好きなカラム追加しても良い。緩さがいいよな。使いやすい。
MySQL以外にSQLiteやPostgreSQLを使う時もほぼ同じだと思う。
pdns のインストール
準備が終わったので、pdnsをインストールすることにする。
sudo yum install pdns
さらに、mysql をバックエンドに使うので mysql-backend をインストールしておく。
sudo yum install pdns-backend-mysql
pdns の設定: mysql
mysql を使うように設定するので
launch=gmysql gmysql-host=127.0.0.1 gmysql-user=pdns gmysql-dbname=pdns gmysql-password=XXXXXXXXXXX
これを書いた。
その後
service pdns restart
接続の確認
nmap localhost
53 番が空くことを確認
dig example.com @127.0.0.1
とりあえず接続して応答は返ってくることを確認。もちろんレコードは何もない。
レコードの追加
サーバーが起動したのでレコードを追加する。
mysql のデータベースにDNSゾーンとDNSレコードとしてテーブルにレコードを追加する。
mysql -p -u pdns pdns
接続できたら、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);
これで、example.com のNSにwwwを登録することが出来た。
問合せてみる
これで完成なので、早速問合せてみる。
dig example.com any @127.0.0.1 ; <<>> DiG 9.9.4-RedHat-9.9.4-29.el7_2.3 <<>> example.com any @127.0.0.1 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36246 ;; flags: qr aa rd; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 2 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1680 ;; QUESTION SECTION: ;example.com. IN ANY ;; ANSWER SECTION: example.com. 120 IN MX 25 mail.example.com. example.com. 86400 IN NS dns-eu1.powerdns.net. example.com. 86400 IN SOA localhost. ahu.ds9a.nl. 1 10800 3600 604800 3600 example.com. 86400 IN NS dns-us1.powerdns.net. ;; ADDITIONAL SECTION: mail.example.com. 120 IN A 192.0.2.12 ;; Query time: 6 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Thu Jul 14 20:15:11 JST 2016 ;; MSG SIZE rcvd: 189
うん、ちゃんと応答する。
HTTP のAPIを準備する。
ちゃんと応答したので、手軽に更新するために curl から叩いたら便利だよね。
MySQLをレコード使えば更新できるので、RailsでMySQL更新するAPIを作っても良いんだけど、最初からあるなら、ソレ使ったほうが楽だよね。
HTTPのAPIを準備する。
webserver=yes webserver-address=127.0.0.1 webserver-port=80 ## experimental-json-interface=yes experimental-api-key=changeme experimental-logfile=/var/log/pdns.log
とりあえず、WEBSERVERをつけたら、状態をモニタリング出来るようになってる。
json-interfaceをオンにしたら、WEB-APIが解放される。楽ね。
API を叩いてみる。
curl -H 'X-API-Key: changeme' http://127.0.0.1:80/servers/localhost/zones
これだけ!あーカンタン。幸せ。
APIはなんでもできるから管理をしっかりしないといけない。
まとめ
最近、ダイナミックDNSが軒並みシンドイ事になってきた。
ダイナミックDNSはスパマーがIPをコロコロ変えるのに利用されたり、クラウドの普及で需要が減ったりしてる。そのため何処も収益化に必死になってきた。
たいへん不自由なので、自分でDNSサーバを作ったほうが良いと判断しました。
DNSの管理は大変だし、乗っ取られたら大変なので注意が必要だし、いろいろと考えることが多い。
でもDNSを自分で管理できるととても便利だし、クラウドが手軽に使えるのにDNSを自由に使えない。結局は、DNSが使い勝手や手軽さのボトルネックになってしまう。
お名前.com のようにTTLが長すぎて変更に時間がかかったり value-domain のように変な挙動する dns だったり。もうね。
GoogleやAmazonのサービスはちゃんとDNSが基本セットに入ってるんだよ。DNS手軽に使えないのものをクラウドと読んでほしくないというか。
参考資料
https://doc.powerdns.com/3/httpapi/README/#powerdns-api