Punycode: зачем нужен и как работает с доменами

Домены на русском, китайском, арабском и других языках работают в DNS благодаря Punycode: алгоритм превращает интернационализированные имена (IDN) в ASCII-строку, с которой умеют работать классические DNS и большинство сетевых утилит.

Что такое Punycode

Punycode – способ кодирования Unicode-меток домена в набор символов LDH (латиница, цифры, дефис). DNS исторически рассчитан на ASCII, поэтому кириллица или иероглифы «как есть» в зоне не живут: их кодируют, а клиенты (браузер, библиотека IDNA) показывают пользователю привычный вид.

Пример: пример.рф в ASCII-форме выглядит как xn--e1afmkfd.xn--p1ai. Префикс xn-- (ACE-префикс) помечает, что метка закодирована через Punycode в рамках IDNA.

Зачем это нужно

  1. Совместимость с DNS. Серверы, резолверы и старые клиенты видят только ASCII. Punycode даёт единый wire-формат без смены протокола DNS.
  2. Интернационализация. Можно регистрировать и использовать имена на родном языке, сохраняя глобальную маршрутизацию имён.
  3. Удобство для людей. В интерфейсе показывается IDN, а в логах, сертификатах, WHOIS и CLI часто видна xn-- форма – обе относятся к одному имени.

Как это устроено

Каждая метка имени (кусок между точками) обрабатывается отдельно. Символы вне базового ASCII кодируются; результат получает префикс xn--. Точка-разделитель меток остаётся точкой. Полное имя собирается из закодированных меток.

  1. Исходное имя: пример.рф
  2. После IDNA/Punycode: xn--e1afmkfd.xn--p1ai
  3. Именно эту строку обычно отправляют в DNS-запросах A/AAAA/MX и т.д.

Стандарты: Punycode описан в RFC 3492, применение к доменам – в IDNA (RFC 5890-5891 и связанные). Для практики достаточно помнить: UI = Unicode, DNS wire = ASCII с xn--.

Как конвертировать

Быстрый вариант в браузере – конвертер Punycode на этом сайте: вставили домен, получили ASCII-форму и обратно.

В Python удобна библиотека idna:

import idna

domain = "пример.рф"
punycode_domain = idna.encode(domain).decode("utf-8")
print(punycode_domain)  # xn--e1afmkfd.xn--p1ai

# обратно
print(idna.decode(punycode_domain))

В shell, если есть подходящие утилиты (зависит от пакетов):

# пример через Python one-liner
python3 -c 'import idna; print(idna.encode("пример.рф").decode())'

В DNS-записях, Certbot/Let’s Encrypt, nginx server_name и почтовых конфигах надёжнее явно указывать xn-- форму или то, что ожидает конкретный софт (многие современные стеки принимают Unicode и кодируют сами).

Фишинг и похожие символы

У Punycode/IDN есть обратная сторона: гомографы. Кириллическая «а» и латинская «a» в шрифте выглядят одинаково, а в DNS это разные кодовые точки и разные имена. Так собирают поддельные домены под известные бренды.

Браузеры частично смягчают риск: при подозрительных смешениях алфавитов в адресной строке показывают Punycode (xn--…), а не «красивый» Unicode. Это не отменяет привычку проверять ссылки, сертификат и источник перехода.

Краткий итог

Punycode – транспортный слой для IDN: люди видят родной алфавит, инфраструктура DNS работает с ASCII. Для админов полезно уметь читать xn-- в логах, WHOIS и сертификатах и при необходимости конвертировать имена. Для пользователей – помнить про гомографный фишинг и не доверять только «похожести» адреса.

Источники и ссылки


Комментарии загружаются…