UnboundとDNSラウンドロビン

今回はキャッシュネームサーバのUnboundがDNSラウンドロビンに対応したので、UnboundとDNSラウンドロビンについて紹介します。

姉妹編『NSDとDNSラウンドロビン』もご覧ください。

Unboundとは

DNSサーバのソフトウェアとしてはBINDがデファクトスタンダードのような位置づけになっていますが、BIND以外にも様々なDNSサーバのソフトウェアがあります。その中の一つとしてUnboundがあります。

UnboundはオランダのNLnet LabsのW.C.A. Wijngaards氏が中心となって開発が行われています。2008年5月20日の正式リリースから4年近く経ち、今では代表的なキャッシュネームサーバのソフトウェアの一つとなっています

Unboundについての詳細は以下のサイトをご覧ください。

DNSラウンドロビン

DNSラウンドロビンはRRset(リソース レコード セット)に複数のRR(リソース レコード)があるときにレスポンス毎にRRの順番を巡回させる機能です。

$ dig www.l.google.com.  ←1回目
;; ANSWER SECTION:
www.l.google.com.	29	IN	A	173.194.38.81
www.l.google.com.	29	IN	A	173.194.38.84
www.l.google.com.	29	IN	A	173.194.38.80
www.l.google.com.	29	IN	A	173.194.38.83
www.l.google.com.	29	IN	A	173.194.38.82

$ dig www.l.google.com.  ←2回目
;; ANSWER SECTION:
www.l.google.com.	25	IN	A	173.194.38.84
www.l.google.com.	25	IN	A	173.194.38.80
www.l.google.com.	25	IN	A	173.194.38.83
www.l.google.com.	25	IN	A	173.194.38.82
www.l.google.com.	25	IN	A	173.194.38.81

ウェブブラウザはRRset内の最初のRRで示されたIPアドレスへアクセスする傾向があるため、この機能を使うと、結果としてウェブサーバへのリクエストの分散ができるので、簡易的な負荷分散クラスターを構成するために使われることがあります。実際のところ、負荷の分散ではなくリクエストの分散なんですけどね。

UnboundとDNSラウンドロビン

UnboundはキャッシュネームサーバとしてBINDの代替(BIND alternative)を謳い文句としてリリースされました。キャッシュネームサーバとして必要な機能はほとんど実装されてはいましたが、BINDで実装されている機能の一部がUnboundには実装されていないため、BINDを置き換えたくてもできないということが言われていました。特に、DNSラウンドロビンの機能が無いので採用できないといった話を私はイベントでよく聞きました。

UnboundでDNSラウンドロビンが実装されてこなかった理由としては、開発者のWijngaards氏はDNSラウンドロビンを実装することによる処理のオーバーヘッドが気になっていたようです。私も以前どうしたらよいのか検討してみたことがあるのですが、ラウンドロビンのオフセットの情報をキャッシュに持たせると、メモリの使用量が増えるし、データ構造も変わるのでダメ。純粋な巡回でなくてもよいので乱数ならどうかなと思いましたが、処理コスト(/dev/randomからのデータ取得、疑似乱数生成のためにハッシュの計算等が必要)のオーバーヘッドが気になるしということでよい案は浮かびませんでした。そんなこんなで正式リリースから4年近く経ちました。

ところが、2012年4月7日にDaisuke HIGASHI氏がunbound-usersメーリングリストに[Unbound-users] patch: rrset-roundrobin/minimal-responsesというタイトルでDNSラウンドロビンを行うパッチを投稿すると、Wijngaards氏はこのパッチのシンプルさを気に入ってあっさりコミットしました。そして、このパッチのrrset-roundrobinオプションの機能が取り込まれたバージョン1.4.17が2012年5月24日にリリースされました。これにより、私たちはUnboundでDNSラウンドロビンの機能が使えるようになったです。なお、デフォルト無効になっているので設定ファイルunbound.confに"rrset-roundrobin: yes"を設定する必要があります。

rrset-roundrobinの実装

ここからは、どのようにUnboundのDNSラウンドロビンが実装されているかを見ていきましょう。

ソースコードのutil/data/msgencode.cのpacked_rrset_encode()関数内の1行を見てみます。

j = (i + rr_offset) % data->count;

ここでjはレコードの順番、iは元の順番、rr_offsetはrrset-roundrobinの設定がyesのときはクエリーIDの数値が入り、noのときは0になります。data->countはRRset内のレコード数です。

文章で表すと「クエリーIDをレコード数で割った剰りをオフセットとする」となります。非常にシンプルです。クエリーID自体はキャッシュポイズニング対策としてランダムに生成されるため、乱雑さの素をクエリーIDを使って再利用したわけです。

なお、実際にこの機能を使ってみるとわかりますが、BINDのようにオフセットが順番に巡回するわけではなく、クエリーIDからオフセットを決定しているため、同じ順番が連続して返されることがあります。サイコロを振った回数が増えるほど出目の回数は均等になるのと同じように、問題はありません。

ということで、今回はリリースされたばかりのUnbound 1.4.17の新機能のDNSラウンドロビンについて紹介してみました。

なお、最後に、私は個人的に日本Unboundユーザー会の中の人だったりします。