Что такое Punycode?
Punycode — синтаксис кодирования, определённый в RFC 3492, который преобразует строки Unicode в ограниченный набор символов ASCII, поддерживаемый DNS. Это техническая основа интернационализированных доменных имён (IDN), позволяющая доменам на любом языке работать с существующей инфраструктурой DNS.
Какую проблему решает Punycode
Система доменных имён была разработана в 1980-х годах с расчётом только на символы ASCII. Метки DNS могут содержать только:
- строчные буквы (a-z)
- цифры (0-9)
- дефисы (-)
Это ограничение исключало миллиарды интернет-пользователей, которые в основном не используют латинский алфавит. Punycode устраняет этот разрыв, кодируя любую строку Unicode в допустимый ASCII.
Как работает кодирование Punycode
Punycode использует алгоритм, который сохраняет символы ASCII и кодирует символы вне ASCII в компактное представление ASCII.
Процесс кодирования
1. Разделение символов: разделить символы на ASCII и не-ASCII
2. Копирование ASCII: сохранить все ASCII-символы на исходных позициях
3. Кодирование не-ASCII: использовать обобщённое целочисленное кодирование переменной длины
4. Добавление префикса: добавить «xn--», обозначающий кодировку Punycode
Примеры
| Исходное имя (Unicode) | Кодированное имя (Punycode) |
|---|---|
| münchen (пример) | xn--mnchen-3ya (пример) |
| 北京 (пример) | xn--fiqs8s (пример) |
| münchen.de (пример) | xn--mnchen-3ya.de (пример) |
| 中文.com (пример) | xn--fiq228c.com (пример) |
| café.com (пример) | xn--caf-dma.com (пример) |
Префикс «xn--»
Префикс «xn--» называется префиксом ACE (ASCII Compatible Encoding, кодировка, совместимая с ASCII). Он сообщает DNS-резолверам и приложениям, что метка содержит содержимое в кодировке Punycode. Этот префикс:
- всегда записывается строчными буквами
- не встречается в обычных доменах ASCII
- запускает декодирование Unicode в совместимом программном обеспечении
Punycode на практике
Обработка браузером
Современные браузеры автоматически обрабатывают Punycode:
User types: 中文.com
Browser sends: xn--fiq228c.com (to DNS)
Browser displays: 中文.com (in address bar)
Реализация для разработчиков
JavaScript (Node.js):const punycode = require('punycode/');
// Encode to Punycode
const encoded = punycode.toASCII('münchen.de');
// Result: xn--mnchen-3ya.de
// Decode from Punycode
const decoded = punycode.toUnicode('xn--mnchen-3ya.de');
// Result: münchen.de
Python:
domain = 'münchen.de'
encoded = domain.encode('idna').decode('ascii')
# Result: xn--mnchen-3ya.de
Работа с URL
При работе с URL, содержащими IDN:
// URL API handles Punycode automatically
const url = new URL('https://中文.com/path');
console.log(url.hostname); // xn--fiq228c.com
console.log(url.href); // https://xn--fiq228c.com/path
Последствия для безопасности
Возможность Punycode представлять любой символ Unicode создаёт риски безопасности:
Визуальная подмена
Злоумышленники могут зарегистрировать домены, визуально совпадающие с легитимными сайтами:
аррlе.com (Cyrillic 'а' and 'р')
apple.com (Latin letters)
В некоторых шрифтах оба имени выглядят одинаково, но являются разными доменами.
Защита браузеров
Для борьбы с подменой браузеры используют защитные механизмы:
1. Обнаружение смешанных скриптов: показывать Punycode для доменов с подозрительным смешением алфавитов
2. Обнаружение визуально похожих символов: отмечать домены с символами, похожими на ASCII
3. Белые списки: разрешать отображение Unicode только для известных TLD
Работа с Punycode в API
При создании доменных инструментов:
Всегда храните Punycode: используйте внутреннюю ASCII-форму для единообразия и индексации базы данных. Принимайте обе формы: позволяйте вводить Unicode или Punycode и преобразуйте их по необходимости. Отображайте Unicode: показывайте человекочитаемую форму в интерфейсах.function normalizeDomain(input) {
const punycode = require('punycode/');
// Convert to lowercase Punycode for internal use
return punycode.toASCII(input.toLowerCase());
}
Punycode прозрачен для большинства пользователей, но необходим разработчикам, создающим интернационализированные веб-приложения.