Skip to content

👻 uTLS: prizrak-utls

uTLS is the library that makes the TLS fingerprint (ClientHello) look like a real browser. It decides which browser a connection looks like for client-fingerprint and REALITY.

mihomo uses metacubex/utls v1.8.8. Prizrak-Core uses its own fork legiz-ru/prizrak-utls (branch v1.9.0-mod-meta-mldsa-chr155). It consists of three parts:

  1. Base: the metacubex v1.9.0-mod-meta branch. It is a newer line than v1.8.8 in mihomo and carries all metacubex changes.
  2. Up-to-date upstream refraction-networking/utls: sync with crypto/tls from Go 1.27.1, the Chrome 155 fingerprint, fixes for compressed certificate decompression, GREASE and PSK fixes, MLKEM1024 key exchange. The fork still builds with Go 1.20.
  3. REALITY ML-DSA-65: see REALITY.
  4. Key shares after the first: the keys of every classical key share are kept, so a server may select any of them (backport of refraction-networking/utls#416, as in Jolymmiles/utls).
client-fingerprintmihomoPrizrak-Core
chromeChrome 133Chrome 155
firefoxFirefox 120Firefox 148
safariSafari 16.0Safari 26.3
ios, android, edge, 360, qqunchangedunchanged

In Prizrak-Core the firefox and safari fingerprints also carry the post-quantum X25519MLKEM768 key exchange, as real browsers of these versions do. In mihomo only chrome has it.

randomized, random and Firefox against P-256

Section titled “randomized, random and Firefox against P-256”
  • randomized always offers X25519MLKEM768 with its key share. uTLS drew twice and independently whether to offer the group and whether to send its key share. Some processes sent the group without the key share: REALITY turned them away, and a server preferring the post-quantum exchange answered with a HelloRetryRequest uTLS could not follow. Some sent the key share without the group, which OpenSSL rejects. Now the hello always offers both and sends key shares for X25519MLKEM768 and X25519 only, as Chrome does, the same fix as in Jolymmiles/Xray-core.
  • random no longer picks ios. ios (iOS 14) sends no X25519MLKEM768, and Xray’s REALITY servers turn such a hello away, so random failed against them on some starts. It now picks chrome, safari or firefox.
  • firefox against servers that select P-256. Firefox fingerprints send key shares for X25519 and P-256, and uTLS kept the key of the first only: a server that selected P-256 failed the handshake with tls: invalid server key share. The key of every share is now kept (part 4 above). The ClientHello is unchanged.