BINDについて(LinuC202学習)
BINDとは
Berkeley Internet Name Domain、略してBIND。DNS権威サーバーおよびキャッシュサーバーとして機能するソフトウェア。
DNSソフトウェアとしては最もトラディショナルかつ一般的だが、インターネットの前面に位置するサーバーという性質と近年の脆弱性の多発と、Amazon Route53やAzure DNSというマネージドサービスを利用したそれらDNS起因のセキュリティ責任のオフロードの動機から、触れる機会は減っていると思われる。
一方で触れることでDNSの内部の働きを体感し、理解を深めることには意義があるとして、触れてみる。
余談:現在BINDなどのセルフホスティングが採用される経緯の考察
プライベートネットワーク上での名前解決を行う際はオンプレミス上ではActive Directoryが出番になることが多かっただろう。
一方でクラウド時代においては認証をOktaなどIDaaSで行うとした場合、名前解決をADに任せっぱなしにしてクラウドリフトすると、片手落ちになる。
もちろんハイパースケーラーはそれらのニーズにも対応している。Amazon Route53 Resolver、Azure プライベートDNSなどがあたる。
これらは各種IaCに対応しており、前述のようなマネージドサービスとしてのメリットが有る一方、高い。
特段考慮せずにポンっと立てた来月のBillingはギャップがすごい。
AWS料金表を確認して比較すると、Resolverエンドポイントあたり0.125 USD/h。これはVPCエンドポイント(インターフェース型)の12.5倍である。
PoC利用において間接的なリソースにお金がかけれない場合はEC2インスタンスでセルフホスティングするのは候補に上げていいと考えられる。
m7a.medium
の料金は USD 0.05796/h、半額未満である。
構築
環境は以下の通り
$ cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
以下はrootユーザーで動作。
apt install bind9
cd /etc/bind
nano named.conf.options
以下記述を追加。実験としてlisten-onの値をローカルループバックアドレスとし、自身のマシンのみで受け付けるようにしている。
options {
+ listen-on { 127.0.0.1; }; #ローカルループバックアドレスを指定
+
+ forwarders {
+ 8.8.8.8; # googleパブリックDNSを指定。
+ };
};
named.serviceデーモンを再起動してステータスを確認し、failedが出ていないことを確認する。
systemctl restart named
systemctl status named
● named.service - BIND Domain Name Server
Loaded: loaded (/usr/lib/systemd/system/named.service; enabled; preset: enabled) # 導入時点で自動有効化が設定されていることが見える
Active: active (running) since Sat 2024-07-13 08:03:19 UTC; 6min ago # activeとなっていれば設定が適用されている
Docs: man:named(8)
Main PID: 2675 (named)
Status: "running"
Tasks: 5 (limit: 1068)
Memory: 5.4M (peak: 5.7M)
CPU: 99ms
CGroup: /system.slice/named.service
└─2675 /usr/sbin/named -f -u bind
Jul 13 08:03:21 bind-server named[2675]: network unreachable resolving './DNSKEY/IN': 2001:7fe::53#53
Jul 13 08:03:21 bind-server named[2675]: network unreachable resolving './DNSKEY/IN': 2001:500:2d::d#53
Jul 13 08:03:21 bind-server named[2675]: network unreachable resolving './DNSKEY/IN': 2001:500:1::53#53
Jul 13 08:03:21 bind-server named[2675]: network unreachable resolving './DNSKEY/IN': 2001:7fd::1#53
Jul 13 08:03:29 bind-server named[2675]: managed-keys-zone: Unable to fetch DNSKEY set '.': timed out
Jul 13 08:03:29 bind-server named[2675]: resolver priming query complete: timed out
Jul 13 08:05:02 bind-server named[2675]: network unreachable resolving './NS/IN': 2001:7fd::1#53
Jul 13 08:05:02 bind-server named[2675]: network unreachable resolving './NS/IN': 2801:1b8:10::b#53
Jul 13 08:05:02 bind-server named[2675]: network unreachable resolving './NS/IN': 2001:500:9f::42#53
restart時にエラーが出てきてしまう場合、構文エラーは標準エラー出力されないため/var/log/syslog
などから特定する必要がある。
確認
キャッシュサーバーとしての動作
構築時点で8.8.8.8
のキャッシュサーバーとして機能できる。
dig @127.0.0.1 www.isc.org
; <<>> DiG 9.18.24-0ubuntu5-Ubuntu <<>> @127.0.0.1 www.isc.org
...
;; Query time: 561 msec # 0.561秒かかっている
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sat Jul 13 08:25:02 UTC 2024
;; MSG SIZE rcvd: 167
dig @127.0.0.1 www.isc.org
; <<>> DiG 9.18.24-0ubuntu5-Ubuntu <<>> @127.0.0.1 www.isc.org
;; Query time: 0 msec # 応答時間が前回より少ない。キャッシュによるもの。
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sat Jul 13 08:25:29 UTC 2024
;; MSG SIZE rcvd: 167
options {
// listen-on { 127.0.0.1; }; # コメントアウト
forwarders {
8.8.8.8; # googleパブリックDNSを指定。
};
};
ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:34:76:c7 brd ff:ff:ff:ff:ff:ff
altname enp0s8
inet 192.168.2.10/24 brd 192.168.2.255 scope global eth1 # 192.168.2.0/24ネットワークにいるのがわかる
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe34:76c7/64 scope link
valid_lft forever preferred_lft forever
systemctl restart named
ufw allow from 192.168.2.0/24 to any port 53 proto tcp
ufw allow from 192.168.2.0/24 to any port 53 proto udp
ufw status
Status: active
To Action From
-- ------ ----
53/tcp ALLOW 192.168.2.0/24
53/udp ALLOW 192.168.2.0/24
今度はクライアントとして別マシンからアクセスしてみる。
以下は別途用意したクライアント用マシンのネットワークデバイスのステータス。サーバーと同じ192.168.2.0/24
ネットワークにいるのがわかる。
vagrant@bind-client:~$ ip a show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:13:bd:0f brd ff:ff:ff:ff:ff:ff
altname enp0s8
inet 192.168.2.20/24 brd 192.168.2.255 scope global eth1 # 192.168.2.0/24ネットワークにいるのがわかる
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe13:bd0f/64 scope link
valid_lft forever preferred_lft forever
暫定的な設定として、/etc/resolve.conf
でサーバーのIPアドレスを設定する。
念の為他のネームサーバーの設定は消しておくのが吉だろう。
+ address 192.168.2.10
クライアント側でdigる。きちんとインターネットのドメイン情報を返してくれる。
vagrant@bind-client:~$ dig www.isc.org
; <<>> DiG 9.18.24-0ubuntu5-Ubuntu <<>> www.isc.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59271
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 58d288cde36de473010000006692484babcff5495443d440 (good)
;; QUESTION SECTION:
;www.isc.org. IN A
;; ANSWER SECTION:
www.isc.org. 4 IN CNAME isc.map.fastlydns.net.
isc.map.fastlydns.net. 60 IN A 151.101.2.217
isc.map.fastlydns.net. 60 IN A 151.101.66.217
isc.map.fastlydns.net. 60 IN A 151.101.130.217
isc.map.fastlydns.net. 60 IN A 151.101.194.217
;; Query time: 450 msec
;; SERVER: 192.168.2.10#53(192.168.2.10) (UDP)
;; WHEN: Sat Jul 13 09:26:35 UTC 2024
;; MSG SIZE rcvd: 167
権威サーバーとしての動作
ここまではキャッシュサーバーとしての動作だが、今日ネームサーバーを自前で作る動機はプライベートネットワーク内の名前解決だろう。
特にクラウドにおけるVPC内DNSはAmazon Route53 Resolverのようなマネージドサービスも存在しているが、イン/アウトバウンドエンドポイントの料金が高い。稼働率よりもコストに軍配が上がる要件においては、自前のDNSをホストするケースもあるはずだ。
権威サーバーとして動作のさせかたを記載する。
ここではBINDサーバー、クライアント、名前解決先のWebサーバーを用意して行う。
example.com
ゾーンの設定(BINDサーバー)
/etc/bind
にnamed.conf.example-zone
を作成する。
zone "example.com" {
type master;
file "/etc/bind/example.com.zone";
allow-query { any; };
allow-transfer { none; };
};
/etc/bind
にexample.com.zone
を作成する。
nano /etc/bind example.com.zone
以下のように編集。
$ttl 60
@ IN SOA . examplemail.example.com. (
20240701 ; serial number
60 ; refresh period
60 ; retry period
60 ; expire time
60 ) ; minimum TTL
@ IN NS .
www IN A 192.168.2.30
wwwのAレコードとして設定しているIPアドレス192.168.2.30
はWebサーバーのIPアドレス。環境に応じて任意のアドレスに変更する。
SOAレコードでこのレコードのメール連絡先examplemail.example.com.
を指定しているが、ここは特に指定はない。
それ以外のSOAレコードについては以下の通り
フィールド | 説明 |
---|---|
20240701 ; serial number | ソーン情報のシリアル番号。単に識別番号のため、この値の変更による名前解決の性質変更はない |
60 ; refresh period | セカンダリサーバーがプライマリサーバーにゾーン情報の更新を確認する間隔。(今回はセカンダリサーバーは設けない) |
60 ; retry period | セカンダリサーバーがゾーン情報を更新できなかった場合に再試行する間隔。 |
60 ; expire time | プライマリサーバーのダウンなどを理由にセカンダリサーバーがゾーン情報を更新できなかった場合、セカンダリサーバーが持っている情報で名前解決を継続できる時間 |
60 ; minimum TTL | ネガディブキャッシュ(問い合わせに失敗したドメインに関するキャッシュ)の保持時間。 |
次に、/etc/bind/named.conf
を以下のように編集し、先程作成したする。
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";
+ include "/etc/bind/named.conf.example-zone";
bindを再起動する。
systemctl restart named
Apacheのホスト(Webサーバー)
Aレコードとして設定した192.168.2.30
であることを確認する。
ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:66:02:b0 brd ff:ff:ff:ff:ff:ff
altname enp0s8
inet 192.168.2.30/24 brd 192.168.2.255 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe66:2b0/64 scope link
valid_lft forever preferred_lft forever
本筋ではないので以下のコマンドでサクッと建てる。
apt update
apt install apache2
systemctl start apache2
curl http://localhost # テストページの表示を確認
ufw allow http
ufw enable
ufw status # 80番の開放を確認
Curlでのドメインの名前解決を通したWebサーバーへのアクセス(BINDクライアント)
resolve.conf
の記述を確認してBINDサーバーをネームサーバーとして利用していることを確認する。
systemd-resolvedが動作している場合はresolve.conf
は自動的に書き換えられうるため、上書きされている場合がある。
cat /etc/resolve.conf
...
nameserver 192.168.2.10
...
以下のコマンドを実行する。出力冒頭で名前解決が行われていることも確認する。
curl -v http://www.example.com
* Host www.example.com:80 was resolved.
* IPv6: (none)
* IPv4: 192.168.2.30
* Trying 192.168.2.30:80...
* Connected to www.example.com (192.168.2.30) port 80
> GET / HTTP/1.1
> Host: www.example.com
> User-Agent: curl/8.5.0
...
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
... # 以下HTMLレスポンス
以上で、BINDネームサーバーによる名前解決と、それを通したドメイン指定によるWebアクセスが行えた。
代替ネームサーバーサービスについて
BIND以外にもネームサーバーサービスが存在しているので軽く紹介。
dnsmasq
小規模なDNSとDHCPサーバーを提供するソフトウェア。DNSとしてはキャッシュサーバーとしての動作と、内部のhostsファイルをもとにした簡易的な名前解決を提供する。
Unbound
DNSキャッシュサーバーとして動作するソフトウェア。キャッシュポイズニングはじめとした攻撃に対する耐性があり、BINDよりも処理性能が高い。
NSD
権威サーバーとして動作するソフトウェア。キャッシュDNSとしては動作しない。
PowerDNS
BINDの次世代的に利用されているDNSソフトウェア。ゾーン情報のデータソースにRDBMSを利用できるほか、WebUIに対応している。性能、攻撃耐性が高い。
Discussion