Punycode 转换(国际化域名)
将包含日语等非 ASCII 字符的国际化域名(IDN)与 Punycode(ASCII 兼容编码)相互转换。
Punycode 是什么
DNS 在历史上只能处理 ASCII 字符。然而人们希望使用像「日本語.jp」这样**含有汉字与假名的域名**,为此搭起桥梁的便是 Punycode(RFC 3492)。它把 Unicode 字符串可逆地转换为以 `xn--` 开头的 ASCII 字符串,从而在不改动既有 DNS 的前提下实现国际化域名(IDN)。
转换结果对人而言不可读,这正是设计使然:`日本語.jp` 会变成 `xn--wgv71a119e.jp`。**浏览器的地址栏会隐去转换后的样貌,改以原本的文字显示**,因此平时并不会意识到它的存在。但这种外观上的落差**也是可被钓鱼攻击利用的弱点**——用西里尔字母「а」冒充拉丁字母「a」之类难以分辨的字符来伪造域名,已经造成过实际的麻烦。本工具可进行双向转换,**所有处理都在浏览器内完成。**
转换的步骤
- 选择转换的方向 在「域名→Punycode」与「Punycode→域名」之间择一。
- 输入域名 请连同顶级域一并输入,如 `日本語.jp`。
- 查看结果 会显示以 `xn--` 开头的转换结果,或还原后的原始文字。
- 对照确认 借由转换后的 ASCII 表示,可确认**是否混入了容易混淆的字符**。
用好本工具的小技巧
- 由多个标签(以 `.` 分隔的部分)组成的域名也会按标签自动判断并转换:仅含 ASCII 字符的标签保持不变,只有包含非 ASCII 字符的标签才会转换为带 `xn--` 前缀的形式。
- 在"Punycode → 域名"模式下,只有包含 `xn--` 前缀的标签会被解码,其余标签将原样保留。
- 该转换逻辑不仅适用于域名,也可应用于邮箱地址中 `@` 之后的部分(域名部分)。
- 在浏览器地址栏中实际输入国际化域名时,大多数浏览器会在内部先转换为 Punycode,然后再进行 DNS 解析。
这些场景会用到
注册或设定中文、日文域名
DNS 区域文件与服务器证书有时需要 Punycode 表示。
确认邮件的发件人
**显示名看似正规,换算成 Punycode 后却是另一个域名**——这样的案例确实存在。
解读日志中出现的 xn--
可查出访问日志或报表中出现的 `xn--` 字符串究竟指向何处。
检验设定文件
可用于确认 nginx 或 Apache 的设定中能否直接书写国际化域名。
Punycode 的术语
- Punycode
- 把 Unicode 字符串可逆地转换为 ASCII 字符串的方式(RFC 3492)。**转换结果必定以 `xn--` 开头。**
- IDN(国际化域名)
- 含有非 ASCII 字符的域名。在内部会被转换为 Punycode 以通过 DNS。
- xn--
- 标示该标签经 Punycode 编码的前缀,称为 ACE 前缀。
- 标签
- 域名以点分隔的各个部分。**转换是逐个标签进行的。**
- 同形异义字攻击
- 以外观极为相似的其他字符伪造域名的手法。**换算成 Punycode 表示便可识破。**
- IDNA
- 为在 DNS 中处理 IDN 而制定的一系列规范,现行为 IDNA2008(RFC 5890 之后)。
常见问题
闲话 ― "猫"与"日本語"如何变成域名的幕后故事
国际化域名(IDN)的讨论始于上世纪 90 年代后期,但标准化经历了很长时间。为了在不改变 DNS 核心结构的前提下处理非 ASCII 字符,业界曾提出多种方案,最终采用了"在应用层(客户端)完成编码与解码,DNS 服务器本身保持不变"的 Punycode 方案,并于 2003 年正式标准化为 RFC 3492。
"Punycode"这个名字据说源自"Unicode"与"an amusing pun"(有趣的双关语)的结合,其算法本身是将更通用的 Bootstring 编码方法(由 IBM 研究人员设计,用于将任意字符集编码为受限字符集的通用方法)针对域名场景加以特化而成。就连"Punycode"这个名字的由来本身也带有几分玩笑意味,颇能体现开发者社区特有的幽默感。
如今,日语域名(`.jp`)以及表情符号域名(例如确实存在的 `💩.la`)等使用各种语言和符号的域名已被实际注册和使用,但在这些域名背后,始终都要经过 Punycode 的转换处理。即便是浏览器地址栏中显示的优美的日语域名,在与 DNS 服务器通信时,实际传输的也是以 `xn--` 开头的朴素 ASCII 字符串。