キャッシュサーバの 設 定 IIJ 山 口 崇 徳 DNS Summer Days 2014
自 己 紹 介 IIJというところでDNSの 運 用 やってます お 客 様 用 参 照 サーバ お 客 様 のゾーンを 預 かる 権 威 サーバ 某 cctldのセカンダリ 最 初 のDNSのお 仕 事 は BIND4 BIND8 の 移 行 前 世 紀 末 その 他 メールやったり web いじったり L7 のなんでも 屋 さん
はじめに BIND Unbound が 対 象 ほかはさわったことないので 設 定 のコピペはできなくても 考 え 方 自 体 は 他 でも 通 用 するは ず 設 定 ファイルの 文 法 レベルの 話 BIND で 権 威 サー バと 共 通 する 設 定 は 触 れません 時 間 が 足 りないっす マニュアル 読 んでください DNSSEC は 触 れません
基 本 設 定
RTFM BIND 9 Administrator Reference Manual ソースアーカイブの bind- 9.x.x/doc/arm/Bv9ARM.html パッケージでインストールすると /usr/{,local/,pkg/}share/doc/ の 下 あたりにあることが 多 い debian は bind9- doc パッケージを 別 途 インストール Unbound は web で hwp://unbound.net/documentayon/ hwp://unbound.jp/unbound/ に 和 訳 あり man も 読 むべし unbound(8), unbound.conf(8) など ぐぐる 前 にまずこちらを 参 照 しよう 残 念 ながらぐぐって 見 つかる 情 報 には 嘘 が 多 いです
最 低 限 の 設 定 BIND 再 帰 検 索 をおこなうことを 明 示 options { recursion yes; }; Unbound デフォルト yes なのでなくても 動 くが 権 威 サーバでないことを はっきりさせるためにも 書 いておくべき 空 っぽでも 動 く 両 者 とも アクセス 制 限 を 追 加 すべし
なぜアクセス 制 限? アクセス 制 限 されていないキャッシュDNSサーバ = オープンリゾルバ DNS amp 攻 撃 の 踏 み 台 にされやすい アドレス 詐 称 クエリによりサイズを 増 幅 させて 帯 域 飽 和 させる 攻 撃 アクセス 制 限 されていれば 影 響 が 限 定 的 になる キャッシュポイズニング 攻 撃 を 受 けやすい アクセス 制 限 があってもポイズニング 攻 撃 自 体 は 可 能 が アクセス 制 限 されていればポイズニングに 成 功 したかどう か 攻 撃 者 は 判 別 が 困 難
BIND: allow- なんとか(1) allow- query サーバへのクエリそのものの 許 可 allow- query- cache キャッシュ 情 報 へのアクセス 許 可 allow- recursion 再 帰 クエリの 許 可 キャッシュサーバを 利 用 する 上 では 以 上 3つすべ てが 許 可 されている 必 要 がある 権 威 サーバでは allow- query だけ 許 可 されていればよい
allow- なんとか(2) allow- query が 設 定 されていない 場 合 すべてのホストからのアクセスが 許 可 される allow- query- cache が 設 定 されていない 場 合 allow- recursion の 設 定 が 使 われる allow- recursion も 未 設 定 なら allow- query が 使 われる allow- recursion が 設 定 されていない 場 合 allow- query- cache の 設 定 が 使 われる allow- query- cache も 未 設 定 なら allow- query が 使 われる allow- query{,- cache} どちらも 未 設 定 なら localhost, localnets が 許 可 される
allow- なんとか(3) allow- hoge はひとつ 設 定 すると 他 の allow- fuga の 設 定 にも 影 響 を 与 える キャッシュサーバとして 利 用 するには 3つすべてが 許 可 されて いる 必 要 があるが ひとつ 設 定 すれば 他 は 設 定 しなくてもした ことになる しかも 条 件 がビミョーに 違 う ひじょーにわかりにくい 横 着 せずに 3つとも 明 示 的 に 記 述 すると 間 違 いが ない
allow- なんとか(4) 以 上 BIND 9.4 以 降 の 話 9.3 まではデフォルトが 違 っていた allow- query- cache は 存 在 しなかった allow- recursion, allow- query どちらも ぜんぶ 許 可 デフォルトでオープンリゾルバ 公 式 にはすでにディスコンになっているバージョン が RHEL4/5 の 標 準 RPM がそれぞれ 9.2 9.3 なので 使 ってい る 人 はいまだに 多 いかと バージョンアップするときには 要 注 意
unboundのアクセス 制 限 access-control: 0.0.0.0/0 refuse access-control: 127.0.0.0/8 allow マッチしたクライアントに 対 する 挙 動 allow: アクセス 許 可 (ただし 非 再 帰 クエリは 拒 否 ) allow_snoop: アクセス 許 可 ( 非 再 帰 も 許 可 ) deny: クエリを 捨 てる( 応 答 を 返 さない) refuse: クエリを 拒 否 する( 拒 否 応 答 を 返 す) {deny,refuse}_non_local 0.0.0.0/0 = ipv4 全 体 ::0/0 = ipv6 全 体
BINDのログ bind のロギングはそれだけで30 分 ぐらい 喋 れそうな ぐらい 細 かい 設 定 ができる そんな 時 間 はないのでばっさり 割 愛 デフォルトではかなり 冗 長 なログを 吐 くので 重 要 度 の 低 いものは 黙 らせておくといいかも logging { category lame-servers { null; }; }; category edns-disabled { null; };
Unboundのログ 設 定 するところほとんどないし 冗 長 度 (verbosity: 1) syslog 経 由 かファイルに 出 力 か(use-syslog: yes) query log を 取 るかどうか(log-queries: no) ぐらいしか デフォルトのままでいいんじゃないかな
クエリログ 規 模 にもよるが ふだんは 出 力 しない 方 がよいかと あっというまにサイズが 膨 れあがるので 調 査 の 必 要 があるときだけ 一 時 的 に 出 力 させる BIND: querylog no; Unbound: log-queries: no 一 時 的 なクエリログ 出 力 の 切 り 替 え BIND: rndc querylog [on off] 9.8 以 前 は on/off 指 定 できない(toggle) Unbound: unbound-control set_option log-queries: [yes no] どちらも 制 御 コマンドを 使 えるように 事 前 準 備 が 必 要
ラウンドロビン BIND RRset ごとに 細 くラウンドロビンの 挙 動 を 設 定 できる が 通 常 は 全 部 まとめて 同 じ 設 定 でよいかと 9.9 のデフォルトはランダム 順 rrset- oder { order random; }; 9.8 までは 循 環 (cyclic) 固 定 順 (fixed)にするには configure - - enable- fixed- rrset 強 いこだわりがなければ random も cyclic もどちらでもよいかと unbound デフォルトはラウンドロビンしない( 固 定 順 ) rrset- roundrobin: yes でランダムに (1.4.17 以 降 )
パフォーマンスチューニング チャンネルはそのまま! この 後 すぐ!! wktk しながら 東 さんのセッションを 待 とう
セキュリティ
キャッシュポイズニング キャッシュサーバが 権 威 サーバに 出 したクエリへの 応 答 として 第 三 者 が 偽 造 応 答 を 割 り 込 ませれば 嘘 の 情 報 をキャッシュさせられるよ 偽 造 応 答 に 必 要 な 情 報 IP アドレス: 1/( 権 威 サーバの 数 ) の 確 率 で 的 中 ポート 番 号 : 16ビット(65536とおり)からひとつ クエリ ID: DNS クエリの 識 別 子 ; 16ビットランダム 値 ポート 番 号 固 定 推 測 の 的 中 確 率 は 1/6.5 万 ポート 番 号 ランダム 的 中 確 率 1/43 億
やっちゃいけない 設 定 query-source port 53; 問 い 合 わせ 元 のソースポート 固 定 禁 止 53 がダメなのではなく 固 定 するのがダメ こうしないとファイアウォールを 越 えられない 場 合 bindではなく FWの 方 を 直 すべし unbound ではふつーに 設 定 していればランダム トリッキーな 方 法 でポート 固 定 もできるがヒミツ
NATとポートランダム 化 (1) NAT 箱 の 裏 側 で 動 くキャッシュサーバに 毒 入 れを 試 みるパケットが 届 くの? 届 きます ポート 番 号 の 推 測 が 的 中 した 場 合 それは NAT テーブルに 載 っている 応 答 パケットの 偽 造 なので NAT 箱 が dst port をちゃんと 書 き 換 えた 上 でキャッシュサーバに パケットを 届 けてくれる 的 中 しなければ NAT テーブルにないので 弾 かれる
NATとポートランダム 化 (2) NAT 箱 がソースポートをどう 書 き 換 えるか 確 認 hwps://www.dns- oarc.net/oarc/services/dnsentropy 結 果 が GREAT となっていればよい わけではない 実 際 に 観 測 されたポート 番 号 (Values Seen) の 値 を 確 認 すべし もし 連 番 (ないしはそれに 近 い 連 続 した 値 )になっていたら GREAT でもダメ 推 測 しやすい NAT 箱 の 入 れ 換 え ネットワーク 構 成 の 変 更 などを 検 討 すべし キャッシュサーバの 設 定 では 対 処 不 可
他 DNSサーバとの 連 携
フォワーダ(1) 自 前 でできない/やりたくない 名 前 解 決 をよそに 回 送 (forward)するというアプローチ よそのキャッシュサーバ = フォワーダ どんなときに 使 うの? グローバルへの 疎 通 のないキャッシュサーバが 疎 通 のある キャッシュサーバに 問 い 合 わせをフォワード 再 帰 検 索 は 遅 いので キャッシュが 溜 まってる 別 サーバにフォ ワード 家 庭 用 ルータの DNS 機 能 はたいていフォワードしてるだけ
フォワーダ(2) ルートサーバ キャッシュサーバ (フォワーダ) キャッシュサーバ レジストリの 権 威 サーバ ユーザ 権 威 サーバ
フォワーダの 設 定 すべての 名 前 解 決 を 別 のキャッシュサーバにフォ ワードする 特 定 ゾーンの 名 前 解 決 だけをフォワードするなら 下 の 例 の "." をそのゾーンに 変 えればよい BIND zone "." { }; type forward; forwarders { 10.0.0.1; }; forward only; Unbound forward-zone: name: "." forward-addr: 10.0.0.1
どこからも 委 任 されないゾーン private.example.jp はどこからも 委 任 されていない どうやって 名 前 解 決 する? 権 威 サーバ. (root) 委 任.jp 委 任 キャッシュサーバ example.jp 委 任 なし ユーザ private.example.jp
内 部 専 用 ゾーンの 名 前 解 決 権 威 サーバはルートサーバから NS レコードを 辿 っ て 探 すのが 基 本 先 の 例 では private.example.jp を example.jp から ふつーに 委 任 しちゃうという 方 法 もできなくはない が 内 部 用 の 委 任 が 外 部 から 見 えちゃうのはよろしくない 正 引 きならともかく 10.0.0.0/8 のようなプライベートアドレスの 逆 引 きゾーン(10.in- addr.arpa) を in- addr.arpa から 自 分 のとこ ろに 委 任 してもらうことはそもそもできない
内 部 専 用 ゾーン localhost とその 逆 引 き 組 織 内 だけで 使 われる 名 前 private.example.jp プライベートアドレスの 逆 引 き 168.192.in- addr.arpa など リンクローカルアドレスその 他 予 約 アドレスの 逆 引 き RFC1918, RFC4193, RFC5737, RFC6303, RFC6598
プライベートアドレスの 逆 引 き(1) ローカルで 名 前 解 決 できるようにする たとえ 逆 引 きなんか 引 けなくてもいいや という 場 合 であっても 空 ゾーン(SOA と NS だけのゾーン)でいいので 用 意 しておく ないとどうなるの? プライベートアドレスの 逆 引 きを 調 べるのに インターネットにクエ リが 出 ていってしまう 障 害 でインターネットとの 疎 通 がなくなると インターネットとは 無 関 係 なイントラ 内 のホストに 対 するアクセスも 困 難 になる(かも)
プライベートアドレスの 逆 引 き(2) BIND Unbound とも 予 約 アドレス 空 間 の 逆 引 き 空 ゾーンが 組 み 込 まれている BIND は 9.5 以 降 空 でない 逆 引 きゾーンが 必 要 なら 自 前 で 用 意 する BIND 9.4 以 前 は 空 ゾーンも 自 前 で 用 意 組 織 内 用 正 引 きゾーン localhost ゾーンも 自 前 で Unbound は localhost も 組 み 込 み どうやって? キャッシュサーバ 自 身 でゾーンを 持 つ 別 の 権 威 サーバにゾーンを 置 いてそちらに 問 い 合 わせる
empty- zones- enable BIND 9.5 以 降 で 組 み 込 みの 逆 引 き 空 ゾーンを 使 う ための 設 定 とくに 理 由 がなければ yes にしておきましょう 有 効 だと 起 動 時 に 大 量 のログが 出 力 される エラーではない このログ 出 力 をやめさせるためにわざわざ no にするという 間 違 った 設 定 例 が 蔓 延 しています 真 似 しないでください あえて no にするのであれば 9.4 以 前 のように 自 前 で 空 ゾーン を 用 意 しましょう
自 前 ゾーン: BIND もともと 権 威 と 共 用 なので 自 前 でゾーンを 持 たせる のはカンタン zone "localhost" { type master; file "localhost.zone"; }; zone "127.in-addr.arpa" { }; type master; file "localhost-rev.zone"; zone "1.0.0.( 略 ).0.0.ip6.arpa" { type master; file "localhost-rev6.zone"; };
自 前 ゾーン: Unbound キャッシュ 専 用 なので 権 威 機 能 は 簡 易 なものだけ localhost ゾーンの 例 (man より) local-zone: "localhost." static local-data: "localhost. 10800 IN NS localhost." local-data: "localhost. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800" local-data: "localhost. 10800 IN A 127.0.0.1" local-data: "localhost. 10800 IN AAAA ::1" 自 前 ゾーンはこんなふうに unbound.conf にいちいち 書 く 必 要 あり localhost ゾーンは 実 際 には 組 み 込 みなので 不 要 実 際 のところ local- data だけでけっこうなんとかなる
ローカルゾーン 専 用 権 威 サーバ BIND でも Unbound でも 内 部 専 用 ゾーンがある 程 度 大 きくなるなら 別 途 専 用 の 権 威 サーバを 構 築 し そちらにクエリを 投 げるようにすべき サーバ 増 設 が 必 要? この 権 威 サーバは 世 界 中 からアクセスされるわけではない 内 部 のキャッシュサーバからのみアクセスできればよい キャッシュサーバと 同 一 ホスト 内 の 別 プロセスでも 十 分 リソースが 競 合 しないように 注 意 ポート 53 ではなく 54 で listen させるとか 127.0.0.2 を 使 うとか pid ファイルその 他 の 置 き 場 所 を 変 える
stub ゾーン 特 定 ゾーンの 名 前 解 決 をDNS の 委 任 ツリーに 含 ま れない 権 威 サーバに 問 い 合 わせる 設 定 動 作 はフォワーダによく 似 ているが 問 い 合 わせ 先 が 権 威 サーバなので 再 帰 要 求 しない ぶっちゃけ forwarder として 設 定 してもちゃんと 動 いてしまう BIND zone "private.example.jp" { }; type stub; masters { 10.0.0.1; }; Unbound stub-zone: name: "private.example.jp" stub-addr: 10.0.0.1
Unbound ハマリどころ stub- zone を 設 定 しても 組 み 込 みの 逆 引 きゾーン の 方 が 優 先 される 組 み 込 みゾーンを 使 わないようにさせる local-zone: "168.192.in-addr.arpa" transparent 権 威 サーバからプライベートアドレスな 応 答 が 返 っ てきても 削 られる プライベートアドレスを 応 答 に 含 んでもよいゾーンを 明 示 する private-domain: "private.example.jp" 権 威 サーバを 同 じホストに 同 居 させると 名 前 解 決 で きない localhost への 問 い 合 わせを 許 す do-not-query-localhost: no
内 部 専 用 ドメイン キャッシュサーバの 設 定 とは 関 係 ないんですが 内 部 用 のドメインとして 勝 手 TLD は 使 わないように しましょう gtld が 現 在 爆 発 的 に 増 加 中 内 部 ドメインとして.mydomain を 利 用.mydomain が 新 規 に gtld として 登 録 される うぎゃー 名 前 衝 突 問 題 (name collision) hwps://www.nic.ad.jp/ja/dom/new- gtld/name- collision/ 内 部 用 に 新 規 ドメインを 取 得 するか 既 存 ドメインの サブドメインを 使 う お 金 かかるけど
まとめ
実 際 に 設 定 してみる こんな 構 成 サーバアドレス 192.168.0.1 内 部 用 正 引 きドメイン private.example.jp ローカルネットワーク 192.168.0.0/24, 2001:db8::/48 アクセス 許 可 もこの 範 囲 からの み 正 引 き 逆 引 きとも 別 途 権 威 サーバ 192.168.0.99 にゾーン がある キャッシュサーバ (192.168.0.1) global 内 部 用 権 威 サーバ (192.168.0.99) 192.168.0/24
named.conf (1) options { // ワーキングディレクトリ directory "/var/named"; // 各 種 出 力 ファイルの 設 定 // directory で 指 定 したところからの 相 対 パス pid-file "log/named.pid"; statistics-file "log/named.stats"; memstatistics-file "log/named.memstats"; dump-file "log/named.dumpdb"; recursing-file "log/named.recursing"; // listen アドレス listen-on { 127.0.0.1; 192.168.0.1; }; listen-on-v6 { any; }; recursion yes; // 再 帰 検 索 する empty-zones-enable yes; // 組 み 込 みの 逆 引 き 空 ゾーンの 有 効 化 querylog no; // クエリログ 取 得 しない minimal-responses yes; // 可 能 なら authority/additional section を 削 る
named.conf (2) }; // アクセス 制 限 allow-query { localhost; private; }; allow-recursion { localhost; private; }; allow-query-cache { localhost; private; }; // 9.4 以 降 // パフォーマンスチューニング recursive-clients 1000; max-cache-size 1G; // アクセス 許 可 ネットワークの 定 義 acl private { 192.168.0.0/24; 2001:db8::/48; };
named.conf (3) // ログ 設 定 // query log はファイルへ 出 力 する // (querylog no; と 設 定 してるので rndc querylog で 有 効 にしたときのみ 出 力 ) // それ 以 外 はデフォルトのまま(syslog) logging { channel log_query { file "log/query.log" versions 5 size 10m; // 10MB でローテーション 5 世 代 print-time yes; }; }; category queries { log_query; }; // 冗 長 なログは 捨 てる category lame-servers { null; }; category edns-disabled { null; }; // rndc の 設 定 include "etc/rndc.key"; controls { inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "rndc-key"; }; };
named.conf (4) // ゾーン 定 義 // ルートヒントはちゃんと 管 理 できないなら 設 定 しなくてもよい zone "." { type hint; file "etc/root.hint"; }; // localhost とその 逆 引 きは 自 前 で 持 つ zone "localhost" { type master; file "etc/localhost.zone"; }; zone "127.in-addr.arpa" { type master; file "etc/localhost-rev.zone"; }; zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" { type master; file "etc/localhost-rev6.zone"; };
named.conf (5) // 内 部 専 用 ゾーンは 専 用 の 権 威 サーバへ zone "private.example.jp" { type stub; masters { 192.168.0.99; }; }; zone "0.168.192.in-addr.arpa" { type stub; masters { 192.168.0.99; }; }; zone "0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa" { // 2001:db8::/48 type stub; masters { 192.168.0.99; }; }; // プライベートアドレスの 逆 引 きは BIND のデフォルトに 任 せるので 設 定 しない // (9.4 以 前 では 別 途 設 定 が 必 要 ) // EOF
unbound.conf (1) server: verbosity: 1 interface: 127.0.0.1 interface: 192.168.0.1 interface: ::0 chroot: "" username: "unbound" directory: "/usr/local/etc/unbound" pidfile: "/var/run/unbound.pid" # ルートヒント; ちゃんと 管 理 できないならコメントアウト root-hints: "/usr/local/etc/unbound/root.hint" # アクセス 制 限 access-control: 0.0.0.0/0 refuse access-control: ::0/0 refuse access-control: 127.0.0.0/8 allow access-control: 192.168.0.0/24 allow access-control: ::1 allow access-control: 2001:db8::/48 allow
unbound.conf (2) # ラウンドロビンさせる rrset-roundrobin: yes # 可 能 なら authority/additional section を 削 る minimal-responses: yes # 応 答 にプライベートアドレスを 含 んでよいゾーン( 内 部 ゾーン) private-domain: "private.exmaple.jp" # 0.168.192.in-addr.arpa は 組 み 込 み 逆 引 きゾーンを 使 わない local-zone: "0.168.192.in-addr.arpa" transparent # localhost への query を 許 容 するかどうか( 今 回 の 例 では yes のままで 問 題 ない) # do-not-query-localhost: no # パフォーマンスチューニング # unbound のデフォルトはかなり 小 規 模 向 けなので 注 意 ( 以 下 の 例 もかなり 控 え 目 ) num-queries-per-thread: 1024 outgoing-num-tcp: 100 incoming-num-tcp: 100 num-threads: 2 msg-cache-size: 512m rrset-cache-size: 512m
unbound.conf (3) # 内 部 専 用 ゾーン stub-zone: name: "private.example.jp" stub-addr: 192.168.0.99 stub-zone: name: "0.168.192.in-addr.arpa" stub-addr: 192.168.0.99 stub-zone: name: "0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa" stub-addr: 192.168.0.99 # localhost とその 逆 引 き プライベートアドレスの 逆 引 きは # デフォルトの 組 み 込 みゾーンをそのまま 使 うので 定 義 しない # unbound-control を 使 えるようにする remote-control: control-enable: yes # EOF