国際化ドメイン名 ( IDN ) について

国際化ドメイン名を使うと、ドメイン名にアルファベットや数字だけでなく日本語を含む様々な文字が利用出来るようになる。自分の書いたコードを、これに対応させるにはどうすればいいか?*1これは、ドメイン名から IP アドレスを得る話なので、名前解決の話である。名前解決といえば、まず思い浮かぶのは getaddrinfo() だろう。

Linux の場合、glibc 2.3.4 からは、AI_IDN というフラグを加えてやることで対応できる。Mac OS XWindows ではそういったフラグは見当たらない。Windows では、IdnToAscii() によって得られた結果を getaddrinfo() に渡すことで国際化ドメイン名に対して名前解決ができるようになる。


では Mac OS X ではどうしているのだろうか、と思い調べてみると、何らかの外部ライブラリを利用している場合があるようだ。例えば、Mac OS X 専用の Twitter クライアントとして有な夜フクロウは、VeriSign が提供している IDN Library を使っているらしい。他にも、GNU が提供しているものや、JPNIC が提供しているものなど様々なライブラリがある。


国際化ドメイン名は結構新しい仕組みなので、プラットフォームごとに対処がばらばらで中々に厄介である。Linux がとった対応方法が一番シンプルに見える。


では、上記ライブラリを使わずに国際化ドメイン名の名前解決をやるにはどうすればいいだろうか?それには、国際化ドメイン名とは何ぞやというのを知る必要がある。

大雑把にまとめるとこのような感じになる。

  1. 国際化ドメイン名に含まれる文字列をそのまま扱うのは既存資産の対応という意味で厳しい
  2. だったら国際化ドメイン名を既存資産が扱える文字列に変換してしまおう
  3. ベースとなる文字コードUTF-32 でいいだろう
  4. 変換方式は Punycode と名付けよう
  5. 実際に国際化ドメイン名を変換するときは、ドメイン名をラベルごとに Punycode で変換し、「xn--」というプレフィクスをつけよう
    1. この際、すべてのラベルが ASCII だけで扱える場合はプレフィクスをつけずにそのままにしておこう
    2. このルールがなく、Punycode でただ変換しても DNS が解釈できる形式にはならない


ここで少し面倒なのが、Unicode のサポートである。が、LinuxMac OS X ならデフォルトで UTF-8Windows なら UTF-16 がサポートされている。そして、Unicode 同士の変換はそんなに複雑ではないのだ。*2


というわけで、実装するなら以下のような処理が必要になる。

  1. UTF-8UTF-16UTF-32 に変換する処理
    1. LE 限定なら、C で書いても 200 行足らずで書ける
  2. Punycode 変換する処理
    1. RFC にのっているコードを参考にして実装できる
    2. C で書いても 200 行足らずで書ける
  3. ドメイン名をラベルで分割する処理
  4. ラベルを Punycode で変換する処理
  5. Punycode で変換したラベルで結合する処理
  6. 必要に応じて「xn--」というプレフィクスをつける処理

試しに書いたコードでは、C で一から書いて全部で 600 行くらいになった。C だとやっぱり長くなるな。JavaScript で書かれた実装なんかもあるので、興味のある方はどうぞ。


IDN はそんなに怖くない、ということで。お粗末。

*1:ブラウザ以外で国際化ドメイン名を利用する機会はまずないだろうが・・・

*2:サロゲートペアさえ正しく扱えれば