TIL:Punycode - 域名中的 Unicode
TIL:Punycode
域名中的 Unicode
之前看了 マリウス 的 disable-javascript.org,我就用 Elfeed 訂閱了他的博客,但後面一直在 Elfeed 裡看到拉取报錯,錯誤信息如下:
[error]: https://マリウス.com/index.xml: "(60) Peer certificate cannot be authenticated with known CA certificates."
Elfeed 是用 curl 發請求的(前提是 elfeed-use-curl 為 t),直接用 curl 請求的話,报錯是:
curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to マリウス.com:443
之後我去問了 Kagi Assistant,經過一些排查後,終於找到了問題。
留意請求的域名,你會發現 你会讶异,你是我最压抑,最深处的秘密 ,我請求的域名是 マリウス.com 。但是 域名只支持 ASCII ,而 マリウス 顯然不是 ASCII ,而是 Unicode。
當你在瀏覧器中輸入域名包含 非 ASCII 字符時,瀏覧器會將其轉成 Punycode 表示:
Punycode 是 Unicode 在受限的 ASCII 字元子集下,用於網際網路主機名稱的表示方式。使用 Punycode 時,包含 Unicode 字元的主機名稱會被轉換為僅由字母、數字與連字號組成的 ASCII 子集,稱為字母‑數字‑連字號(letter–digit–hyphen, LDH)子集。
例如, マリウス.com 會被編碼為 xn--gckvb8fzb.com ,其中的 gckvb8fzb 是 マリウス 對應的 Punycode,xn-- 是一個固定的 國際化域名 (International Domain Names, IDN) 前綴。
檢查我現在的 curl (curl -V),看到的是:
curl 8.7.1 (x86_64-apple-darwin25.0) libcurl/8.7.1 (SecureTransport) LibreSSL/3.3.6 zlib/1.2.12 nghttp2/1.68.1 Release-Date: 2024-03-27 Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp Features: alt-svc AsynchDNS GSS-API HSTS HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM SPNEGO SSL threadsafe UnixSockets
裡面沒有 IDN 相關的功能,所以是無法处理 マリウス.com 這樣的 IDN 的。
知道問題就好辦了,讓 curl 支持 IDN 就好,我用 homebrew 下載了新的 curl:
# 先安裝新版本
brew update
brew install curl
# 設到 PATH 的前面,优先用 homebrew 的版本
export PATH="$(brew --prefix)/opt/curl/bin:$PATH"
裡面就包含 IDN:
curl 8.21.0 (aarch64-apple-darwin25.4.0) libcurl/8.21.0 OpenSSL/3.6.4 zlib/1.2.12 brotli/1.2.0 zstd/1.5.7 AppleIDN libpsl/0.23.3 libssh2/1.11.1 nghttp2/1.70.0 ngtcp2/1.25.0 nghttp3/1.18.0 mit-krb5/1.7-prerelease OpenLDAP/2.4.28/Apple Release-Date: 2026-06-24 Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt mqtts pop3 pop3s rtsp scp sftp smtp smtps telnet tftp ws wss Features: alt-svc AppleSecTrust AsynchDNS brotli GSS-API HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Kerberos Largefile libz PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd
用這個版本的 curl 進行請求,就能正常返回了。
如果 curl 不支持 IDN 也不想更新,用 Ponycode 形式的域名 (xn–gckvb8fzb.com) 就好。
另外 マリウス 也寫了篇文章解釋他的域名,感興趣也可以看看: NEVER click on a link that looks like that。
脚注:
相關規𫈣:
- RFC 5891 - Internationalized Domain Names in Applications (IDNA): Protocol
- RFC 3492 - Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)
感谢你的阅读!
欢迎 邮件 跟我分享你的想法 :)
你也可以 我的博客,保持更新 :P
祝好,素未某面的读者。