はじめに
この記事では、Rocky Linux 9 上に PowerDNS のパッケージ群を使って自宅用の DNS サーバを構築する手順を記載する。
自宅DNSサーバ構成
この記事では、下記のような構成で構築する。
項目 | 設定 |
---|---|
ハードウェア | Proxmox VE が構築済みの仮想環境 |
OS | Rocky Linux 9 (LXC コンテナ) |
メモリ | 2GB |
ストレージ | 20GB |
DNS 権威サーバ | PowerDNS Authoritative Server |
DNS リゾルバ | PowerDNS Recursor |
DNS プロキシ&ロードバランサー | PowerDNS DNSdist |
DNS バックエンド DB | MariaDB |
DNS 権威サーバ用 WebUI | PowerDNS-Admin (Docker) |
DNS サーバ構成図
構築手順
設定パラメータ
各サーバの設定値を先にまとめておく。記事内のスクリプトの値を、各自の環境に合わせて書き換えること。
システム | 項目 | 設定 |
---|---|---|
DNSサーバ | ホスト名 | dns01 |
DNSサーバ | IPv4 アドレス | 192.0.2.50/24 |
DNSサーバ | IPv4 デフォルトゲートウェイ | 192.0.2.1 |
DNSサーバ | IPv6 アドレス | 2001:DB8::32/64 |
DNSサーバ | IPv6 デフォルトゲートウェイ | 2001:DB8::1/64 |
DNSサーバ | 上位DNSフォワード先アドレス | 1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001 |
MariaDB | バージョン | 11.4 (LTS) |
MariaDB | root パスワード | 6g8nS9QSC5HDhdbx |
MariaDB | pdnsadmin ユーザーパスワード | 3mwH1QeuiMV53157 |
PowerDNS DNSdist | バージョン | 1.9.8 |
PowerDNS DNSdist | Listen Port | UDP/TCP 53 |
PowerDNS DNSdist | Web UI password | 36J55V7jUk0D |
PowerDNS DNSdist | Web API Key | ab164a08-1775-4dff-a633-4a9b542605e2 |
PowerDNS Authoritative Server | バージョン | 4.9 |
PowerDNS Authoritative Server | DNS Listen Port | UDP/TCP 25301 |
PowerDNS Authoritative Server | API KEY | faa5b1ce-1495-4fce-9129-735078a675f2 |
PowerDNS Authoritative Server | API Listen port | 8081 |
PowerDNS Recursor | バージョン | 5.1 |
PowerDNS Recursor | Listen Port | UDP/TCP 25302 |
PowerDNS-Admin | バージョン | 0.4.2 |
PowerDNS-Admin | Listen Port | TCP 9191 |
DNSゾーン | ゾーン名 | home |
DNSゾーン | IPv4 セグメント | 192.0.2.0/24 |
DNSゾーン | IPv6 セグメント | 2001:DB8::/64 |
- IPv4 / IPv6 アドレスは、それぞれ RFC 5737 / RFC 3849 に従って例示用アドレスを記載
- パスワードは develop.tools | パスワード生成ツール で作成
- API キーは develop.tools | UUID生成ツール で作成
- 「上位DNSフォワード先アドレス」はプロバイダ提供の IP アドレス、または Public DNS を指定
- 例では Cloudflare の IPv4/IPv6 アドレスを指定している
MariaDB インストール
dnf リポジトリ設定
MariaDB 11.4 LTS版 の例
MARIADBVERSION=11.4
cat <<__EOT__> /etc/yum.repos.d/mariadb.repo
[mariadb]
name = MariaDB
baseurl = https://rpm.mariadb.org/${MARIADBVERSION}/rhel/\$releasever/\$basearch
gpgkey= https://rpm.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
__EOT__
インストール
dnf install -y MariaDB-server
systemctl enable mariadb
systemctl start mariadb
MariaDB 初期設定
初期セキュリティ設定値
mariadb-secure-installation
Enter current password for root (enter for none):
[Enter]
Switch to unix_socket authentication [Y/n]
y[Enter]
Change the root password? [Y/n]
y[Enter]
6g8nS9QSC5HDhdbx
6g8nS9QSC5HDhdbx
(MariaDB の root ユーザーのパスワードを2回入力)
Remove anonymous users? [Y/n]
y[Enter]
Disallow root login remotely? [Y/n]
y[Enter]
Remove test database and access to it? [Y/n]
y[Enter]
Reload privilege tables now? [Y/n]
y[Enter]
ログ設定変更
/etc/my.cnf.d/server.conf 内 vi で編集 ※デフォルトだと警告メッセージが出すぎるため
[mysqld]
log_warnings = 1
MariaDB 初回ログイン
パスワードを聞かれるので、設定したパスワードでログイン
# mariadb -u root -p
Enter password: 6g8nS9QSC5HDhdbx[Enter]
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 2397
Server version: 11.4.4-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
PowerDNS 用のユーザーを設定
CREATE DATABASE pdns;
GRANT ALL ON pdns.* TO pdnsadmin@localhost IDENTIFIED BY '3mwH1QeuiMV53157';
FLUSH PRIVILEGES;
設定確認
SHOW GRANTS FOR pdnsadmin@localhost;
下記の中身が表示されればOK
Grants for pdnsadmin@localhost
[Ctrl]-[D] で抜ける
PowerDNS パッケージ群インストール
レポジトリセットアップ
参考: https://repo.powerdns.com/
PowerDNS Authority 4.9 / PowerDNS Recursor 5.1 / dnsdist 1.9 の例
PDNS_AUTH_VER=49
PDNS_RECURSOR_VER=51
PDNS_DNSDIST_VER=19
curl -o /etc/yum.repos.d/powerdns-auth-${PDNS_AUTH_VER}.repo https://repo.powerdns.com/repo-files/el-auth-${PDNS_AUTH_VER}.repo
curl -o /etc/yum.repos.d/powerdns-rec-${PDNS_RECURSOR_VER}.repo https://repo.powerdns.com/repo-files/el-rec-${PDNS_RECURSOR_VER}.repo
curl -o /etc/yum.repos.d/powerdns-dnsdist-${PDNS_DNSDIST_VER}.repo https://repo.powerdns.com/repo-files/el-dnsdist-${PDNS_DNSDIST_VER}.repo
パッケージインストール
dnf install -y pdns pdns-backend-mysql pdns-recursor dnsdist
PowerDNS 用に MariaDB セットアップ
DBのパスワードを聞かれたら入力
mariadb -u pdnsadmin -p pdns < /usr/share/doc/pdns-backend-mysql/schema.mysql.sql
XXXXXXXXXXXX
PowerDNS Auth (Authoritative Server) / Recursor 設定
PDNS Auth オリジナル設定バックアップ
cp -a /etc/pdns/pdns.conf /etc/pdns/pdns.conf.DEFAULT
PDNS_AUTH_BASE='/etc/pdns'
PDNS_RECURSOR_BASE='/etc/pdns-recursor'
# UUID生成ツール等で作成
PDNS_AUTH_APIKEY='faa5b1ce-1495-4fce-9129-735078a675f2'
MARIADB_PASSWORD='3mwH1QeuiMV53157'
# CloudFlare の場合
UPSTREAM_DNS_IPv4_1=1.1.1.1
UPSTREAM_DNS_IPv4_2=1.0.0.1
UPSTREAM_DNS_IPv6_1=2606:4700:4700::1111
UPSTREAM_DNS_IPv6_2=2606:4700:4700::1001
# PDNS Auth config
cat <<__EOT__ >${PDNS_AUTH_BASE}/pdns.conf
api=yes
api-key=${PDNS_AUTH_APIKEY}
webserver=yes
webserver-address=0.0.0.0
webserver-allow-from=127.0.0.0/8
webserver-port=8081
launch=gmysql
gmysql-socket=/var/lib/mysql/mysql.sock
gmysql-user=pdnsadmin
gmysql-password=${MARIADB_PASSWORD}
gmysql-dbname=pdns
local-address=127.0.0.1 ::1
local-port=25301
security-poll-suffix=
setgid=pdns
setuid=pdns
# log-dns-details=yes
# log-dns-queries=yes
log-timestamp=yes
# logging-facility=0
# loglevel=7
dnsupdate=yes
allow-dnsupdate-from="127.0.0.0/8, ::1/128"
__EOT__
chgrp pdns ${PDNS_AUTH_BASE}/pdns.conf
chmod 640 ${PDNS_AUTH_BASE}/pdns.conf
# PDNS Recursor config (YAML形式)
cat <<__EOT__ >${PDNS_RECURSOR_BASE}/recursor.d/recursor.yml
incoming:
listen:
- 127.0.0.1
- ::1
allow_from:
- 127.0.0.0/8
- '::1/128'
port: 25302
tcp_fast_open: 100
outgoing:
tcp_fast_open_connect: true
source_address:
- 0.0.0.0
- '::'
recursor:
extended_resolution_errors: true
serve_rfc1918: false
hint_file: no-refresh
forward_zones_recurse:
- zone: .
forwarders:
- ${UPSTREAM_DNS_IPv4_1}
- ${UPSTREAM_DNS_IPv4_2}
- ${UPSTREAM_DNS_IPv6_1}
- ${UPSTREAM_DNS_IPv6_2}
lua_config_file: ${PDNS_RECURSOR_BASE}/recursor.d/nta.lua
logging:
# loglevel: 7
# common_errors: true
# quiet: false
timestamp: true
# trace: false
__EOT__
echo "Creating syslog configuration:"
mkdir -p /var/log/powerdns
chmod a+w /var/log/powerdns
cat <<__EOT__ > /etc/rsyslog.d/powerdns.conf
if ($programname contains 'pdns-recursor') then {
action(type="omfile" file="/var/log/powerdns/pdns-recursor.log")
}
if ($programname contains 'pdns_server') then {
action(type="omfile" file="/var/log/powerdns/pdns-auth.log")
}
__EOT__
echo "Creating logrotate configration:"
cat <<__EOT__ > /etc/logrotate.d/powerdns
/var/log/powerdns/*.log
{
missingok
sharedscripts
postrotate
/usr/bin/systemctl -s HUP kill rsyslog.service >/dev/null 2>&1 || true
endscript
}
__EOT__
systemctl reload rsyslog.service
systemctl enable pdns-recursor.service
systemctl restart pdns-recursor.service
systemctl enable pdns.service
systemctl restart pdns.service
dnsdist 設定
PDNS dnsdist オリジナル設定バックアップ
mkdir /var/log/dnsdist
cp -a /etc/dnsdist/dnsdist.conf /etc/dnsdist/dnsdist.conf.ORG
web api key の生成
$ dnsdist -l 127.0.0.1:5300 -C /dev/null
> hashPassword('ab164a08-1775-4dff-a633-4a9b542605e2')
$scrypt$ln=10,p=1,r=8$7aMm9zGGfidk3qBQJ5TIgQ==$CAO2O0SnvfHnCKbftNf+qfrar4cgPhB0TREc1p89dHU=
console key の生成
$ dnsdist -l 127.0.0.1:5300 -C /dev/null
> makeKey()
setKey("J7lAScDbcLtFGVtXsZf8eKxWj0/4+4NJ3Mb7BkFseHc=")
サービス設定
# 決めておいた設定パラメータからコピペする
WEBPASSWORD="36J55V7jUk0D"
# 上記 dnsdist 内で生成した値をコピペする
WEBAPIKEY='$scrypt$ln=10,p=1,r=8$7aMm9zGGfidk3qBQJ5TIgQ==$CAO2O0SnvfHnCKbftNf+qfrar4cgPhB0TREc1p89dHU='
# 上記 dnsdist 内で生成した値をコピペする
CONSOLEKEY='J7lAScDbcLtFGVtXsZf8eKxWj0/4+4NJ3Mb7BkFseHc='
LOCALIP='192.0.2.50'
LOCALSEGMENTV4='192.0.2.0/24'
LOCALSEGMENTV6='2001:DB8::/64'
FORWARD_ZONE="home"
PTR_ZONE="2.0.192.in-addr.arpa"
cat <<__EOT__ > /etc/dnsdist/dnsdist.conf
-- disable security status polling via DNS, we know we're EOL
setSecurityPollSuffix('')
-- Set Netmask Group
-- https://dnsdist.org/reference/netmaskgroup.html
allowQueryAddresses = newNMG()
allowQueryAddresses:addMask('127.0.0.0/8')
allowQueryAddresses:addMask('::1/128')
allowQueryAddresses:addMask('fe80::/64')
allowQueryAddresses:addMask('${LOCALSEGMENTV4}')
allowQueryAddresses:addMask('${LOCALSEGMENTV6}')
allowUpdateAddresses = newNMG()
allowUpdateAddresses:addMask('${LOCALSEGMENTV4}')
allowUpdateAddresses:addMask('${LOCALSEGMENTV6}')
-- ACL of DNS query
-- https://dnsdist.org/advanced/acl.html
setACL('0.0.0.0/0')
addACL('::/0')
-- dnsdistのListenサーバIPアドレス:使用ポート
-- https://dnsdist.org/reference/config.html#listen-sockets
-- https://dnsdist.org/reference/config.html#setLocal
-- https://dnsdist.org/reference/config.html#addLocal
-- set primary listen address
setLocal('0.0.0.0:53')
addLocal('[::]:53')
-- バックエンド: IPアドレス:使用ポート、バックエンド名、秒間クエリ制限数
-- https://dnsdist.org/reference/config.html#newServer
newServer({address='127.0.0.1:25301', name='authoritive', pool={'auth'}})
newServer({address='127.0.0.1:25302', name='recursor', pool={'resolver'}})
-- ロギング設定
-- https://dnsdist.org/reference/actions.html#LogAction
-- LogAction([filename[, binary[, append[, buffered[, verboseOnly[, includeTimestamp]]]]]])
-- クエリのデバッグをする際のみ、下記のコメントを外す
-- addAction(AllRule(), LogAction('/var/log/dnsdist/query.log', false, false, false, true, true))
-- [How to generate key]
-- https://dnsdist.org/guides/console.html
-- dnsdist -l 127.0.0.1:5300 -C /dev/null
-- > makeKey()
setKey('${CONSOLEKEY}')
controlSocket('${LOCALIP}:5199')
setConsoleACL({
'${LOCALSEGMENTV4}',
'192.168.2.0/24'
})
-- SuffixMatchNode
-- https://dnsdist.org/reference/config.html#suffixmatchnode
authdomains = newSuffixMatchNode()
authdomains:add(newDNSName('${FORWARD_ZONE}.'))
authdomains:add(newDNSName('${PTR_ZONE}.'))
-- 振り分けルール
-- https://dnsdist.org/reference/rules-management.html
-- https://dnsdist.org/reference/actions.html
addAction(
SuffixMatchNodeRule(authdomains),
PoolAction('auth')
)
addAction(
OpcodeRule(DNSOpcode.Update),
PoolAction('auth')
)
addAction(
NetmaskGroupRule(allowQueryAddresses),
PoolAction('resolver')
)
-- dnsdist dashboard
-- https://dnsdist.org/guides/webserver.html
-- https://dnsdist.org/reference/config.html#webserver
webserver('0.0.0.0:8083')
setWebserverConfig({
password='${WEBPASSWORD}',
apikey='${WEBAPIKEY}',
acl='0.0.0.0/0,::/0'
})
__EOT__
systemctl enable dnsdist.service
systemctl start dnsdist.service
ゾーン登録例
初期登録テスト用として、ゾーン情報を pdnsutil
コマンドで登録する。
PDNS_RECURSOR_BASE='/etc/pdns-recursor'
ZONE="home"
PTR_ZONE="2.0.192.in-addr.arpa"
SOA_MASTER="dns01.${ZONE}."
SOA_CONTACT="hostmaster.${ZONE}."
SOA_SERIAL=0
SOA_REFRESH=28800 # 8 hours
SOA_RETRY=3600 # 1 hour
SOA_EXPIRE=2419200 # 28 days
SOA_NEGATIVE=900 # 15 minutes
SOA_RECORD="${SOA_MASTER} ${SOA_CONTACT} ${SOA_SERIAL} ${SOA_REFRESH} ${SOA_RETRY} ${SOA_EXPIRE} ${SOA_NEGATIVE}"
RR_TTL=3600 # 1 hour
LOCAL_SEGMENT=""
# clear zone
pdnsutil delete-zone "${ZONE}"
pdnsutil delete-zone "${PTR_ZONE}"
## SAMPLE ZONE ENTRY
# Create Forward lookup zone
pdnsutil create-zone "${ZONE}"
pdnsutil set-kind "${ZONE}" native
pdnsutil replace-rrset "${ZONE}" @ SOA "${SOA_RECORD}"
pdnsutil add-record "${ZONE}" @ NS dns01.${ZONE}.
## DNSサーバ自身の正引き登録
pdnsutil add-record "${ZONE}" dns01 A 192.0.2.50
pdnsutil add-record "${ZONE}" dns01 AAAA '2001:DB8::32'
# Create Reverse lookup zone
pdnsutil create-zone "${PTR_ZONE}"
pdnsutil set-kind "${PTR_ZONE}" native
pdnsutil replace-rrset "${PTR_ZONE}" @ SOA "${SOA_RECORD}"
pdnsutil add-record "${PTR_ZONE}" @ NS dns01.${ZONE}.
## DNSサーバ自身の逆引き登録
pdnsutil add-record "${PTR_ZONE}" 50 PTR dns01.home.
recursor に NTA を登録
DNSSEC 検証エラーを抑止するため、ローカルゾーンを NTA (Negative Trust Anchor) として登録する。
これを設定しないと名前解決できずに悩む。
cat <<__EOT__ > ${PDNS_RECURSOR_BASE}/recursor.d/nta.lua
addNTA('${ZONE}', 'internal domains')
addNTA('${PTR_ZONE}', 'private ptr zone')
__EOT__
systemctl restart pdns-recursor.service
PowerDNS の WebUI を追加
docker engine 導入
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
dnf install -y docker-ce docker-compose-plugin
# change bridge network
cat <<'__EOT__' >/etc/docker/daemon.json
{
"default-address-pools":[
{
"base":"172.29.0.0/16",
"size":24
}
]
}
__EOT__
# start dockerd
systemctl enable docker.service
systemctl start docker.service
PowerDNS-Admin 導入 (docker)
作成済みの PowerDNS Authoritative Server 用 API KEY を貼る。
docker run -d \
-e SECRET_KEY='faa5b1ce-1495-4fce-9129-735078a675f2' \
-v pda-data:/data \
-p 9191:80 \
--restart always \
powerdnsadmin/pda-legacy:latest
PowerDNS-Admin 初回設定
ブラウザでアクセス http://192.0.2.50:9191/
ユーザー登録する
- Create an account
- First Name: FIRSTNAME
- Last Name: LASTNAME
- Email: [email protected]
- Username: xxxx
- Password: XXXXXXXXX
WebUI内で設定
※わかりにくいが、PowerDNS Authoritative Server の IP は、Docker の内部から見たホスト自身になるため、docker0 ブリッジの先頭 IP アドレスを指定する。
- PowerDNS API URL: http://172.29.0.1:8081/
- PowerDNS API Key: faa5b1ce-1495-4fce-9129-735078a675f2
設定が完了すると、Web UI からゾーン編集ができるようになる。
起動順序調整
デフォルトだと、再起動時の起動順序で失敗することがあるため、systemd の設定に依存関係を追記する。
/usr/lib/systemd/system/pdns.service に追記
[Unit]
#中略
Wants=mariadb.service
After=mariadb.service
/usr/lib/systemd/system/pdns-recursor.service に追記
[Unit]
#中略
After=pdns.service
/usr/lib/systemd/system/dnsdist.service に追記
[Unit]
#中略
After=pdns.service pdns-recursor.service
systemd に反映
systemctl daemon-reload
動作確認
再起動後のサービス確認
プロセス確認
ps axuw | grep "pdns|dnsdist"
pdns_server, pdns_recursor, dnsdist のプロセスが上がっているか確認。
dnsdist 185 0.1 3.9 2108992 83432 ? SLsl Jan04 14:28 /usr/bin/dnsdist --supervised --disable-syslog
pdns-re+ 2350190 0.0 1.3 420764 28412 ? Ssl 18:27 0:07 /usr/sbin/pdns_recursor --daemon=no --write-pid=no --disable-syslog --log-timestamp=no
pdns 2378134 0.0 2.9 677380 62080 ? SLsl 20:43 0:00 /usr/sbin/pdns_server --guardian=no --daemon=no --disable-syslog --log-timestamp=no --write-pid=no
ログにエラーが出ていないか確認
less /var/pdns-auth.log
less /var/pdns-recursor.log
外部問合せテスト
サーバ上の dig コマンドでテスト。
# dig +noall +ans @localhost blog.yamk.net A
blog.yamk.net. 216 IN A 172.67.199.171
blog.yamk.net. 216 IN A 104.21.21.177
# dig +noall +ans @localhost blog.yamk.net AAAA
blog.yamk.net. 300 IN AAAA 2606:4700:3032::ac43:c7ab
blog.yamk.net. 300 IN AAAA 2606:4700:3033::6815:15b1
内部問合せテスト
# dig +noall +ans @localhost dns01.home A
dns01.home. 3600 IN A 192.0.2.50
# dig +noall +ans @localhost dns01.home AAAA
dns01.home. 3600 IN AAAA 2001:DB8::32
逆引きも試す。
# dig +noall +ans @localhost -x 192.168.0.24
24.0.168.192.in-addr.arpa. 3600 IN PTR dns01.home.
PC端末から問合せテスト
PC端末の Windows PowerShell から、DNS サーバを指定して問い合わせてみる。
Resolve-DnsName
コマンドレットでは -Type A_AAAA
オプションで IPv4 と IPv6 アドレスを同時にクエリできる。
外部ホスト
Resolve-DnsName -Name blog.yamk.net -Server 192.0.2.50 -Type A_AAAA
Name Type TTL Section IPAddress
---- ---- --- ------- ---------
blog.yamk.net AAAA 176 Answer 2606:4700:3033::6815:15b1
blog.yamk.net AAAA 176 Answer 2606:4700:3032::ac43:c7ab
blog.yamk.net A 99 Answer 172.67.199.171
blog.yamk.net A 99 Answer 104.21.21.177
内部ホスト正引き
Resolve-DnsName -Name dns01.home -Server 192.0.2.50 -Type A_AAAA
Name Type TTL Section IPAddress
---- ---- --- ------- ---------
dns01.home AAAA 3600 Answer 2001:DB8::32
dns01.home A 3600 Answer 192.0.2.50
内部ホスト逆引き
Resolve-DnsName -Name 192.168.0.24 -Server 192.168.0.24 -Type PTR
Name Type TTL Section NameHost
---- ---- --- ------- --------
50.2.0.192.in-addr.arpa PTR 3600 Answer dns01.home
仕上げ
もろもろテストして問題なさそうなら、家庭内 LAN の DHCP サーバで配布している DNS サーバのアドレスを、上で構築した DNS サーバに変更する。念のため、フォールバック先として元の DNS サーバも残しておく。
例:
- プライマリ DNS サーバ: 192.0.2.50 ※新規構築した DNS
- セカンダリ DNS サーバ: 192.0.2.1 ※元々の DNS サーバ(ブロードバンドルータなど)
各端末の参照先が新規 DNS サーバに向いたら、さらにテストを繰り返して安定性を確認する。
以上。
余談
ブロードバンドルータやホームゲートウェイ内蔵の DNS 機能ではなく、敢えて独立 DNS サーバを用意することで ネットが快適になる。構築リソースとか維持コスト等の状況が許すなら自宅 DNS 構築はお勧めである。自力で構築したからといって、すべてが解決するわけではないが、得るものは必ずある。
ただし DNS の知識はそれなりに必要なので、中途半端な運用で上位 ISP に迷惑を掛けないよう心がけたい。
「自宅 DNS」の2つの意味
自宅 (または小規模の事務所など) の DNS として求められているものは、主に2つある。
(1) 外部インターネットアクセス用の DNS
Webサイト閲覧や各種動画アプリ、ネットワークゲーム、オンラインサービス等で、外部へアクセスするときは必ず DNS が使用される。
PC やスマホ端末から現代的な Web サイトを見る場合、1回のアクセスでも Javascript やフォントダウンロード・アクセス解析・広告など、多数のサイトに横断して複雑な送受信が走る。
一方、近年普及してきた Akamai や Cloudflare に代表される CDN (コンテンツデリバリネットワーク) は、
- 世界中に多数のコンテンツサーバが配置され
- 問い合わせるたびにホスト IP が変わる (冗長化+ネットワーク距離最適化)
という特徴があるため、DNS キャッシュ保持時間が短く設定されている。すなわち、同じ URL へのアクセスでも頻繁に DNS リクエストが発生する。
DNS キャッシュとか DNS プロキシといった機能は、ブロードバンドルータや ISP が提供するホームゲートウェイも内蔵されている。ただし制御範囲が狭く、大抵「名前解決のパフォーマンス」もそれなりであるため、DNS の応答速度向上は体感に影響する。
また IPv6 の普及により応答データ量が DNS 当初の仕様 (512バイト) を越えることも多くなったため、レスポンスが落ちる TCP フォールバックではなく、EDNS0 によるメッセージサイズ拡張 に対応していてほしい。
ブロードバンドルータの DNS の不具合で、インターネットアクセスが不安定になってしまった事例もある。
- サイトに接続できないと頻繁に表示されるようになりました。 Google Chrome ヘルプ, 2022-11-15
- とあるプロバイダが提供している 「NEC Aterm の問題」らしいとユーザーが特定
- DNS クエリの TCP フォールバックが 10 個が応答待ちになると、それ以上の問合せができなくなる
- Google Chrome の挙動が変わり、ルータ内蔵 DNS の不具合があぶり出された
(2) ローカルサーバ用の DNS
Linux サーバを複数立て始めると、欲しくなってくるのが内部ホスト名でのアクセスである。
古くは NBT (NetBIOS over TCP/IP), Apple の Bonjour, LLMNR, 最近では mDNS といった 同じセグメント内で自動的にホスト名とIPアドレスを紐づけるといった技術 は存在するが、ブロードキャストやマルチキャストが届く範囲でしか名前解決できないため、セグメントを分けた瞬間にホスト名が見えなくなってしまう。
自分の場合、仮想環境内に仮想ルータを立ててセグメントを分けたり、外部から OpenVPN で自宅 LAN に入ってきたりしているので、分かりやすいホスト名でアクセスできるようにしておきたい。
「ホスト名+ドメイン」と「IPアドレス」を直接紐づけるサーバを 権威サーバ (Authoritative Server) と呼び、ブロードバンドルーター・ホームゲートウェイにも簡易版がついていることもあるが、あまり使いやすくはない。
自宅ネットワーク内の各種ホスト名は変化するので、Web 管理画面等でメンテナンスしやすくしておきたい。
PowerDNS 所感
- PowerDNS Recursor は設定ファイルが YAML に移行したが、Authoritative Server は従来のまま。
- PowerDNS Dist に至っては Lua 形式で超わかりにくい。
- 性能はともかく、同じブランドであれば設定方法も統一してほしい‥‥。
- キャッシュ DNS 性能だけなら Unbound の方がよさそう。
残テーマ
- Kea DHCP で自宅内 DHCP サーバ
- もうブロードバンドルータなんてファイアウォールと NAT だけで十分
- Kea DHCP の日本語記事が少ない上にいろいろ仕様変更が
- Kea DHCP サーバと連動して、動的ホスト名登録を DNS へ登録
- できそうだが未確認
参考
- BINDに替わるDNSサーバ〜PowerDNS〜 デージーネット
- BIND辞められない理由 Q&A 株式会社インターネットイニシアティブ 島村 充, 2016/6/24