#はじめに
手元に余っているRaspberry Pi 1 Model Aがあったので、自宅のLAN内で動作するDNSサーバをたてた話をします。
#前提
- raspbian wheezy
root@raspberry-pi:~# lsb_release -da
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 7.11 (wheezy)
Release: 7.11
Codename: wheezy
- PowerDNS 4.0.1
- PowerDNS-Admin githubのmasterブランチ
今回、Raspberry Piが初代の古いもののためか、raspberrypi.orgのRASPBIAN JESSIE だとうまくsshで接続できなかったので、wheezyを使っています。
また、ドメイン登録のためのWebFrontEndにPowerDNS-Adminを使いたかったので、WebAPIの機能からexperimentalが抜けている現時点で最新のPowerDNS 4.0.1を ソースコードからコンパイルしてインストールしています。
全体としてとりあえず動かすことを重視しています。セキュリティ的な観点が欠落しているので、ご留意ください。
PowerDNSのインストール
ソースコードのダウンロード
前提で話したように、現時点で最新のバージョンを使いたかったので、4.0.1のソースコードをダウンロードして解凍する。
# wget https://downloads.powerdns.com/releases/pdns-4.0.1.tar.bz2
# tar xvfj pdns-4.0.1.tar.bz2
依存のインストール
# apt-get update && apt-get upgrade
# apt-get install g++ libboost-all-dev libtool make pkg-config libmysqlclient-dev libssl-dev
# apt-get install flex
# apt-get install libbison-dev
# apt-get install libmysqld-dev mysql-server mysql-client
バックエンドにgmysqlを使うので、MySQLもインストールします。
コンパイルとインストール
# cd pdns-4.0.1
# ./configure
# make
# make install
./configure --help
すると、いろいろなオプションがでるので、必要なものを設定してください。今回は、とくに設定を加えることなく、そのままコンパイルしました。
また、コンパイル途中でエラーがでたら、エラーを確認して、足りないライブラリなどをインストールしてください。実際、コンパイルしている時に、boostに関連するエラーがでたので、libboost-dev
からlibboost-all-dev
を追加でインストールして解決しました。
MySQLの設定
DNSのレコードを管理するデータベースとテーブルをMySQL上に作成します。今回は、面倒だったので、rootで管理するようにしてしまっていますが、実際はセキュリティのために専用のMySQLのユーザを作成してください。
# mysql -uroot -p -e 'CREATE DATABASE powerdns'
# mysql -uroot -p powerdns < modules/gmysqlbackend/schema.mysql.sql
ソースコードの中のmodules/gmysqlbackend/schema.mysql.sql
にスキーマ情報があるので、それを実行します。
設定
gmysqlを使うための設定と、PowerDNS-Adminを使うためのAPIの設定をします。
ソースコードからコンパイルしてインストールした場合は、設定ファイルは/usr/local/etc/
になります。pdns.conf-dist
を複製して編集します。
# cp /usr/local/etc/pdns.conf-dist /usr/local/etc/pdns.conf
編集箇所は以下になります。
diff pdns.conf-dist pdns.conf
50c50
< # api=no
---
> api=yes
55c55
< # api-key=
---
> api-key=your-powerdns-api-key
245c245
< # launch=
---
> launch=gmysql
540c540
< # webserver=no
---
> webserver=yes
---
> gmysql-host=localhost
> gmysql-dbname=powerdns
> gmysql-user=root
> gmysql-password=yourpassword
api-key
は、PowerDNSのWebAPIを使うための任意の文字列になります。PowerDNS-Adminの設定でも使います。
起動
動作確認のために、コマンドから実行して動作を確認します。
# pdns_server
Jan 02 04:28:46 Reading random entropy from '/dev/urandom'
Jan 02 04:28:46 This is a standalone pdns
Jan 02 04:28:46 Listening on controlsocket in '/var/run/pdns.controlsocket'
Jan 02 04:28:46 UDP server bound to 0.0.0.0:53
Jan 02 04:28:46 UDPv6 server bound to [::]:53
Jan 02 04:28:46 TCP server bound to 0.0.0.0:53
Jan 02 04:28:46 TCPv6 server bound to [::]:53
Jan 02 04:28:46 PowerDNS Authoritative Server 4.0.1 (C) 2001-2016 PowerDNS.COM BV
Jan 02 04:28:46 Using 32-bits mode. Built using gcc 4.7.2 on Dec 31 2016 07:28:24 by root@raspberry-pi.
Jan 02 04:28:46 PowerDNS comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it according to the terms of the GPL version 2.
Jan 02 04:28:46 Listening for HTTP requests on 0.0.0.0:8081
Jan 02 04:28:46 Polled security status of version 4.0.1 at startup, no known issues reported: OK
Jan 02 04:28:46 Creating backend connection for TCP
Jan 02 04:28:46 About to create 3 backend threads for UDP
Jan 02 04:28:46 Done launching threads, ready to distribute questions
試しに別のshellを起動してdigを実行してみます。
# dig @127.0.0.1
; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @127.0.0.1
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 8397
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;. IN NS
;; Query time: 14 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Jan 2 04:27:27 2017
;; MSG SIZE rcvd: 17
正常に動作していないと、not foundと表示されると思います。
一度、Ctrl + c
でpdns_serverを終了して、サービス起動スクリプトを用意します。
スクリプトはソースコード内のpdns/pdns.init
を利用します。
# cp pdns/pdns.init /etc/init.d/pdns
# chmod +x /etc/init.d/pdns
複製したスクリプトのコメントの下、変数を定義する最初のところにPowerDNSをインストールしたフォルダのプリフィックスを追加します。
diff pdns/pdns.init /etc/init.d/pdns
18c18
<
---
> prefix=/usr/local
サービスから実行してみます。
# service pdns start
Starting PowerDNS authoritative nameserver: started
# service pdns status
16887: Child running on pid 16889
service pdns status
と実行して、pdnsが動いていることが確認できます。
以上で、PowerDNSの設定は完了です。
PowerDNS-Adminのインストール
まず、githubからソースコードをcloneしてきます。
# git clone https://github.com/ngoduykhanh/PowerDNS-Admin.git
MySQLの設定
PowerDNS-Adminのデータを管理するようのデータベースをMySQL上に作ります。
# mysql -uroot -p -e 'CREATE DATABASE powerdnsadmin'
依存のインストール
pythonを使うので、それに関連するものをインストールします。
# apt-get install python-pip
# pip install MySQL-python
# pip install virtualenv
# cd PowerDNS-Admin
# virtualenv flask
# source ./flask/bin/activate
(flask)# pip install -r requirements.txt
設定
設定ファイルの雛形があるので、複製します。
(flask)# cp config_template.py config.py
必要となる設定は、上で作成したMySQLへ接続するための設定とPowerDNSのWebAPIにアクセスするための情報になります。
diff config_template.py config.py
6,7c6,7
< SECRET_KEY = 'We are the world'
< BIND_ADDRESS = '127.0.0.1'
---
> SECRET_KEY = 'abcdefghijkl' # 適当な文字列
> BIND_ADDRESS = '0.0.0.0' # とりあえず外部からみえるように一時的に
25,27c25,27
< SQLA_DB_USER = 'powerdnsadmin'
< SQLA_DB_PASSWORD = 'powerdnsadminpassword'
< SQLA_DB_HOST = 'mysqlhostorip'
---
> SQLA_DB_USER = 'root'
> SQLA_DB_PASSWORD = 'yourpassword'
> SQLA_DB_HOST = '127.0.0.1'
73,75c73,75
< PDNS_STATS_URL = 'http://172.16.214.131:8081/'
< PDNS_API_KEY = 'you never know'
< PDNS_VERSION = '3.4.7'
---
> PDNS_STATS_URL = 'http://127.0.0.1:8081/'
> PDNS_API_KEY = 'your-powerdns-api-key' # PowerDNSの設定で作成したAPI Keyを記述
> PDNS_VERSION = '4.0.1'
起動
起動する前に、データベースにスキーマの情報を流します。
(flask)# ./create_db.py
無事、成功したらPowerDNS-Adminを実行します。
(flask)# ./run.py
[INFO] * Running on http://0.0.0.0:9393/ (Press CTRL+C to quit)
[INFO] * Restarting with stat
[WARNING] * Debugger is active!
[INFO] * Debugger pin code: 246-032-548
9393ポートにブラウザでアクセスして、ログイン画面が表示されることを確認してください。
初期ユーザは用意されていないので、Create an account
をクリックして、ユーザを登録してログインできることを確認します。
ドメインの登録とドメインを使ったアクセス
次に、せっかくなのでPowerDNS-Adminへドメイン名pdns.rp.local
を使ってアクセスできるようにします。
PowerDNS-Adminからドメインを登録
左側のメニューのNew Domainをクリックします。
表示されたページの、Enter a valid domain name (required)
と書かれている入力エリアにrp.local
と入力します。他は、そのままでSubmit
をクリックします。
登録が完了すると、Dashboardの下部のHosted Domainsに登録したドメインが表示されていることが確認できます。
次に、rp.localのManageをクリックします。ここからレコードを登録することができるのでpdnsという名前でAレコードを追加します。IPアドレスは、Raspberry PiのIPアドレスを登録します。
Saveしたあと、右上にある、Apply Changesをクリックします。確認のモーダルが表示されるので、Applyをクリックすると設定が反映されます。
Nginxのインストール
特に最新のNginxの機能などを使う予定はないので、apt-getで普通にインストールします。
# apt-get install nginx
VirtualHostとプロキシの設定
9393ポートで動いているPowerDNS-Adminをドメイン付きでプロキシします。/etc/nginx/conf.d
に設定ファイルを追加します。
server {
listen 80;
server_name pdns.rp.local;
location / {
proxy_pass http://localhost:9393;
}
}
必要最低限の設定なので、必要に応じて設定を追加してください。
念のためconfigtestをしてスクリプトに問題がないことを確認したあとNginxを再起動します。
# service nginx configtest
Testing nginx configuration: nginx.
# service nginx restart
クライアント側のDNSの設定
最後にクライアント側の参照するDNSサーバに、Raspberry PiのIPアドレスを追加します。
通常ですと、ルータのDHCPサーバの設定に追加したりすると思うのですが、設定する場所が見つけられなかったので……。今回はMacのネットワーク設定に追加しました。自分の場合は、Raspberry PiのローカルIPが192.168.179.2
となっているので、これを追加します。
ブラウザから、http://pdns.rp.local/
にアクセスしてページが表示できることを確認します。
あとがき
当初、別のUbuntuマシンにDockerを使ってPowerDNSとPowerDNS-Adminを立てようと考えてました。ところが、libvirtが使っているdnsmasqと53/udpで衝突してしまい、どう頑張っても解決できませんでした。
そこで、Dockerを動かしていないまっさらなRaspberry Pi上のLinuxならできるだろうと思い、なんとか動作させることができました。