Amazon EC2上に2台のサーバを作り、その上で内部向けDNSサーバを動かしたときに、DNS は TCP でも問い合わせできるのだと改めて知った。

server1 と server2 があり、server1 で DNS サーバが稼働している。server1 から server1 に対して nslookup すると瞬時に答が返ってくるのに、server2 から server1 に対して nslookup するとワンテンポ遅れる。おそらく1秒未満の遅れだが、こんなに遅いはずがない。

実は、server1 と server2 の間で udp/53 の通信が許可されていないことが原因だった。Amazon EC2 では、同じセキュリティグループのインスタンス同士でも、明示的に許可してやらなければ通信できない。Passive mode の FTP を使いたかった関係上、TCP は全通しにしてあったが、UDP は閉じたままだった。

こういうときリゾルバは、UDP での通信を試みたあとに、TCP を試す。この UDP の失敗を待つ時間が、ワンテンポの遅れになっているのだろう。DNS における TCP はゾーントランスファーでのみ使われるものと思っていたが、通常の問い合わせでも使われることを学んだ。

RFC 1035 Domain Implementation and Specification を見ると、UDP でも TCP でも使えるけど、オーバーヘッドの少ない UDP の方が好ましいと書かれていた。

4.2. Transport

The DNS assumes that messages will be transmitted as datagrams or in a byte stream carried by a virtual circuit. While virtual circuits can be used for any DNS activity, datagrams are preferred for queries due to their lower overhead and better performance. Zone refresh activities must use virtual circuits because of the need for reliable transfer.

実装上は、UDP のデータグラムサイズを超える場合や、今回のように UDP での問い合わせに失敗した場合に TCP が使われるようになっているようだ。