Punycode と国際化ドメイン名(IDN):日本語URLの裏側で起きていること

約6分

日本.jp のような日本語ドメインを使うと、URL バーには日本語のまま表示されますが、DNS の裏側では Punycode と呼ばれる ASCII 表記に変換されています。仕組みと、それに関わるセキュリティ上の罠を整理します。

DNS の制約:ASCII しか扱えない

DNS の仕様は ASCII のみを前提に設計されました:

  • ホスト名に使える文字:英字、数字、ハイフン、ドット
  • 大文字小文字は区別しない
  • 最大 63 文字(ラベル単位)

日本語や他の Unicode 文字をそのまま入れることはできません。これを回避するために考案されたのが IDNA(Internationalizing Domain Names in Applications) で、その中核技術が Punycode です。

Punycode:Unicode を ASCII にエンコード

Punycode(RFC 3492)は Unicode 文字列を ASCII の英数字とハイフンだけで表現する可逆エンコーディング。

例:

元のドメインPunycode
日本.jpxn--wgv71a.jp
münchen.dexn--mnchen-3ya.de
пример.рфxn--e1afmkfd.xn--p1ai

xn-- プレフィックスが「これは Punycode エンコード済みのラベル」を示します。

エンコードの中身(簡略)

Punycode は次のステップで動作:

  1. ASCII 文字をそのまま左に並べる
  2. 残りの非 ASCII 文字を、コードポイント順 + 出現位置で連続的にエンコード
  3. 結果を xn--<encoded> の形式にする

ASCII 文字を含むドメイン(mañana.com のように)は、man をそのまま残し、ñ の位置と文字情報をエンコードします。

ホモグラフ攻撃:似た見た目で別の文字

Punycode の存在によって生まれたセキュリティリスクが ホモグラフ攻撃です。

例:以下の 2 つは見た目がほぼ同じ:

  • apple.com(普通の ASCII)
  • аpple.coma がキリル文字の а

後者は Punycode で xn--pple-43d.com のような別ドメインとして登録できます。ユーザーが「apple.com」と思ってアクセスすると、別のサイトに誘導される。

これを防ぐため、ブラウザは 同一ドメイン内に複数のスクリプト(文字体系)が混在する場合、Punycode 表記で表示する仕様になっています。

ブラウザの表示判定基準

Chrome・Firefox の判定(簡略):

  • ドメインが完全に ASCII または完全に同一スクリプト(例:すべて日本語)→ Unicode で表示
  • 複数スクリプトが混在(例:ラテン + キリル)→ Punycode で表示
  • 一部の許可された組み合わせ(日本語 + ASCII 数字など)→ Unicode で表示

このため、日本.jp は日本語のまま表示されるが、аpple.com(キリルの а)は xn--pple-43d.com として表示される。

メールアドレスの国際化(EAI)

メールアドレスの EAI(Email Address Internationalization、RFC 6530) も同様の課題に対処しています:

  • ローカルパート(@ の左)も Unicode 対応
  • ドメインパートは IDNA(Punycode)

ただし EAI 対応のメールサーバーはまだ少なく、実用上は ASCII 限定で運用するケースが多いです。

実装で扱う場面

1. ドメイン入力フォーム

ユーザーが「日本.jp」と入力したものをサーバーで検証する場合:

const domain = 'xn--wgv71a.jp'; // Punycode
const display = '日本.jp'; // 表示用

URL オブジェクトのプロパティを参照すると Punycode 化されたドメインが取れます。

2. メール送信

Sender: 山田@example.com のようなアドレスは、Punycode 化したドメインで SMTP に渡す必要があります。

3. SSL 証明書

Let’s Encrypt などは IDN ドメインに対して ACME プロトコルで Punycode 表記の証明書を発行します。

4. 検索エンジンインデックス

Google は同一ページの IDN 形式と Punycode 形式を別 URL として扱うため、canonical を統一する必要があります。

まとめ

  • DNS は ASCII のみ → Punycode で Unicode を ASCII 化する
  • xn-- プレフィックスがエンコード済みラベルの目印
  • ホモグラフ攻撃の脅威があり、ブラウザは混在スクリプトを Punycode 表示する
  • 実装ではフォーム入力、メール、SSL、SEO 各場面で意識する

日本.jp のような IDN を Punycode に変換したい場合、本サイトの Punycode 変換ツールでエンコード・デコードを試せます。