日本語ドメインが xn-- になる理由:国際化ドメイン名と Punycode

日本語.jp が DNS の設定画面や SSL 証明書で xn--wgv71a119e.jp と表示される理由、Punycode が文字を英数字に置き換えるしくみ、変換前の正規化、ホモグラフ攻撃までを RFC をもとに整理しました。

開発Unicodeネットワーク

日本語.jp のような日本語ドメインを取得すると、ブラウザのアドレスバーには日本語のまま表示されるのに、DNS の設定画面や SSL 証明書の申請フォームでは xn--wgv71a119e.jp と書くように求められます。打ち間違いのような文字列ですが、これも同じドメインです。日本語の名前は人のための表示で、xn-- で始まるほうがネットワーク機器の間で実際にやり取りされる名前です。

インターネットの名前は英数字しか通らない

初期に決められたホスト名の規則では、使える文字は英字・数字・ハイフンだけです(LDH ルールと呼ばれます)。DNS サーバー、メールサーバー、ファイアウォール、何十年も使われてきたソフトウェアは、どれもこの前提で作られています。それを一度に変えることはできないので、逆に日本語の名前を英数字だけで書き表す方法が決められました。その規則が IDNA(Internationalized Domain Names in Applications)で、現在の版は RFC 5890〜5893(IDNA2008)です。

IDNA は2つの形を区別しています。

名前 例 使われる場所
U-label 日本語 人が読み、入力する形
A-label xn--wgv71a119e DNS・証明書・HTTP のリクエストが実際に運ぶ形

xn-- は「このラベルは変換済み」という目印で、ACE プレフィックスと呼ばれます。変換はドット(.)で区切られたラベルごとに行い、jp のようにもともと英数字のラベルはそのまま残します。

Punycode:英数字は残し、残りは「どこに何を」

ラベルを A-label に変えるアルゴリズムが Punycode(RFC 3492)です。英字にウムラウト付きの文字が1つ混ざったドイツ語の bücher を例にすると、しくみが見えやすくなります。

Bücher.example が xn–bcher-kva.example になるまでの流れ。手順1の UTS #46 マッピングで小文字にそろえ、bücher.example になります。手順2の Punycode(RFC 3492)では、bücher のうち英字 b、c、h、e、r を順番どおりに残し、ハイフンの後ろの kva に「b の後に ü(U+00FC)を入れる」という情報を入れます。手順3で xn– を付けて A-label の xn–bcher-kva.example になります。ほかの例として、日本語.jp は xn–wgv71a119e.jp、한국어.com は xn–3e0bk47br7k.com になります。

  1. ラベルから英数字だけを順番どおりに書き出します。bcher
  2. 英数字が1つでもあれば、後ろにハイフンを付けます。
  3. 抜けた文字(ü、U+00FC)について、どの位置に入るかと文字の番号を1つの数にまとめ、その数を英数字で書きます。kva

こうして bücher は bcher-kva になり、プレフィックスを付けて xn--bcher-kva です。日本語 のように英数字を1つも含まないラベルは、手順1で残るものがないのでハイフンなしで wgv71a119e になります。文字番号の差を可変長で書く方式なので、番号の近い文字が続けば短く、離れた文字が混ざると長くなります。

変換の前に整える

Punycode に通す前に、ブラウザは入力を整えます。この規則は Unicode 技術標準 UTS #46 にあります。

  • 大文字は小文字になります。Bücher と bücher は同じドメインです。
  • 全角英字の ABC.jp は abc.jp に、日本語入力で打った句点「。」はドットとして扱われます。日本語。jp と打っても xn--wgv71a119e.jp に届きます。
  • 互換文字は基本の形になります。昔のドイツ語の ſ(長い s)は s になります。

ただし、すべてがまとめられるわけではありません。ドイツ語の ß は、古い規則(IDNA2003)では ss に置き換えられていましたが、今のブラウザは ß のまま残し、faß.de を xn--fa-hia.de として送ります。規則の移行期には、同じ入力でもソフトウェアによって行き先が違うことがありました。

長さの上限は A-label で数える

DNS のラベル1つは63バイトまでです(RFC 1035)。この上限は見た目の文字数ではなく、変換後の A-label の長さにかかります。漢字とかなを混ぜた長いラベルで試すと、文によって20〜26文字ほどで63に届きました。同じ文字の繰り返しや番号の近い文字ばかりなら、もっと長く書けます。正確な上限は、実際に変換した結果で確かめるのが確実です。

xn– を見かける場所

  • DNS の設定画面:レコードを追加するとき、A-label を求めるサービスが多くあります。
  • SSL/TLS 証明書:証明書のドメイン名(SAN)には A-label が入ります。証明書の詳細を開くと xn-- が見えます。
  • HTTP のリクエストとアクセスログ:ブラウザはリクエストの Host ヘッダーに A-label を入れて送ります。サーバーのログやアクセス解析にもこの形で残ります。
  • メール:受け取る側のサーバーが国際化メール(SMTPUTF8、RFC 6531)に対応していなければ、アドレスのドメイン部分は A-label にして送ります。@ の前まで日本語のアドレスにはこの逃げ道がなく、相手側が対応していないと届きません。

見た目は同じ、中身は別:ホモグラフ攻撃

国際化ドメインには副作用もあります。キリル文字の а(U+0430)はラテン文字の a と形が同じなので、аpple.com は目では区別できませんが、A-label にすると xn--pple-43d.com というまったく別のドメインです。

そのため、ブラウザはいつも Unicode の形で表示するわけではありません。Chrome や Firefox は、1つのラベルの中で文字体系が不自然に混ざっていたり、有名なドメインと紛らわしかったりすると、アドレスバーに xn-- の形をそのまま表示します。判断の基準は UTS #39(Unicode Security Mechanisms)をもとにしています。漢字+ひらがな+カタカナ+英字のように実際の言語で一緒に使う組み合わせは認められるので、普通の日本語ドメインは日本語で表示されます。見覚えのない xn-- がアドレスバーに出ていたら、一度疑ってみる価値があります。

2つの形を行き来するとき

DNS レコードや証明書に入れる値を確かめたいときや、ログに残った xn-- がどのドメインかを知りたいときは、Punycode 変換ツールに入れてみてください。日本語ドメインを入れると A-label を、xn-- で始まる値を入れると元の名前を表示します。URL をそのまま貼り付けてもホスト名だけを取り出し、入力はブラウザの中だけで処理します。

参考

  • RFC 3492, Punycode: A Bootstring encoding of Unicode for IDNA
  • RFC 5890〜5893, Internationalized Domain Names for Applications (IDNA)
  • Unicode Technical Standard #46, Unicode IDNA Compatibility Processing
  • Unicode Technical Standard #39, Unicode Security Mechanisms
  • RFC 1035, Domain Names – Implementation and Specification
  • RFC 6531, SMTP Extension for Internationalized Email

ブログへ