2012年09月03日

ネームサーバ移転と共有ホスティングからの転出時障害

ネームサーバの移転時には正しく移転シないといつまでも古い情報が残り続ける。といういわゆる『DNS浸透言うな』の http://www.e-ontap.com/dns/propagation/pinning.html 
についてhttps://twitter.com/tomyuk 氏からご指摘いただいた。

概説すると、
DNSでは委任元と委任先で同じNSレコードが設定されていることを要求している。もし、この前提が崩れて委任元と委任先で異なるレスポンスが帰ったらどうすべきか? 委任関係の原則から言って、委任の情報を優先して、間違った委任先を無視するべきである。ところが、古いキャッシュサーバでは委任先の情報を信用してしまう=キャッシュが古い情報で汚染されるというバグがある。

ルートからたどれば間違っているとわかるため、DNSキャッシュサーバーがリブート(キャッシュを消去)されると正しい情報になったように見える。
リブート頻度はISPのメンテ頻度によってまちまちなので、あるプロバイダでは接続できて、あるプロバイダだけ接続できない、という状況が発生しうる。
そして実際に発生した http://www.e-ontap.com/dns/propagation/

これを防ぐには、
ネームサーバを切り替える時には移転元のゾーンも移転先と同じ新しいゾーンに更新すること
が最大の解決法になる。
逆に言えば、共有ホスティングのユーザーが、共有DNSに所有ドメインを委任していた時に、何も考えず委任元のNSレコードだけ差し替えた場合、このバグにヒットする場合がある。ユーザーのDNSへの認識レベルによってはありうる事態だ。

氏の指摘は、このシナリオにおいてもプロなら顧客が安全に利用できる手段を取るべきだ、というものだと自分は解釈した。
自分はそんなシナリオでの障害は自己責任であって、DNSのよく言われる注意点を確認しない最悪シナリオだ、と考慮の埒外に置いていた。

その点を反省し、より安全な設定を考える。

まず、単純に移転元のDNSの設定や改善では無理がある。委任元のNSが変わったことを、master/slaveゾーン持ちの(自身を権威と思っている)サーバが知る術は無いからだ。これは外部的に情報を与えてやるしか無い。

自分が考えうるのは、

1.@ IN NSレコードをhint扱いとする。つまり通常はauth/additionalセクションを返さないようにして、委任元サーバへの問い合わせ結果を得てから、それを返したりゾーン転送に使用することを許可する。そうすれば負荷が上がるかもしれないが汚染は起きない。これはBIND設定でできるかもしれない。探してみる。
additional-from-auth, additional-from-cacheをnoにすることで意図的にNSをクエリしない限り大丈夫とは思うのだが。

2.定期的にルート(か信頼出来るtld)からキャッシュなしのdig traceして、対応するNSレコードが一致するかチェックする。(上位サーバのNSにはmasterがあるのだからキャッシュ汚染されることはあり得ない。)

一日あたり1クエリくらいして、もしNSが予想外に変更されていたら、 "@ IN NS namesever" だけを上書きした新しいゾーンに自動更新する。
他のレコードが間違っているかも知れないが、NSさえ更新されていれば、TTL時間内にキャッシュ汚染は消える。

という事でもしより安全かつユーザフレンドリな実装を行いたいとしたら、2の手段を提案する。
さくらのように極端に多数のゾーンを一括ホストしているのでも無い限り、TLDのサーバに一箇所から負担をかけたり、処理に時間がかかりすぎる(ほとんどの利用者は多段委任なんてしないだろう。)なんてことは無いと考える。 少なくともWHOISを確認したりするよりもずっと安全だし、低コストだろう。

#こういう不正な委任関係をチェックしてゾーン編集するスクリプトはDNSやるとき一回は書いてみたことあると思う。スクリプト言語の練習にもなるし。

大変長いこと暇人に付き合っていただいた  @tomyuk @beyondDNS 両氏に感謝。
posted by ko-zu at 01:35| Comment(0) | TrackBack(0) | セキュリティ | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
×

この広告は90日以上新しい記事の投稿がないブログに表示されております。