DNSTT: other/dnstt/server.pub belongs to a different key pair than the private key the service runs with — clients built from server.pub can never connect

Author: eveiljuiceCreated Sep 13, 2026Updated Sep 13, 2026

Describe the bug

A DNSTT client configured with the public key from other/dnstt/server.pub never establishes a session (client waits at "connecting"; no valid handshakes on the server). The same client configured with hconfig dnstt_public_key connects immediately.

There are two independent DNSTT key sources on a default install, and they are never synchronized:

  1. The panel generates its own pair on first init and stores it in the DB — panel submodule (hiddify/hiddifypanel), hiddifypanel/panel/init_db.py (~lines 26–27):

    python
    add_config_if_not_exist(ConfigEnum.dnstt_private_key, key_pair['private_key'])
    add_config_if_not_exist(ConfigEnum.dnstt_public_key,  key_pair['public_key'])

    The rendered systemd unit (other/dnstt/run.sh.j2run.sh) uses this DB private key: ExecStart=... dnstt-server -privkey <db private key> ...

  2. other/dnstt/install.sh (~line 16) exports a static file as the client-facing key:

    bash
    export PUBLIC_KEY_FILE=/opt/hiddify-manager/other/dnstt/server.pub

    server.key/server.pub are created at install time and belong to a different pair (observed on a 12.3.3 install: file timestamps from install day, keys distinct from the DB pair).

So the server encrypts with the DB pair while the "public" file advertised for clients is from another pair. There is no configuration under which the two sources agree, and the failure mode (client silently never connects) gives the user no hint which key is wrong.

To Reproduce

  1. Fresh 12.3.3 install, add a domain with mode dnstt, apply.
  2. Start the tunnel service; confirm it runs with the DB private key (-privkey in the unit's ExecStart).
  3. Configure a client with the contents of other/dnstt/server.pub.
  4. Client never completes a session.
  5. Reconfigure with hconfig dnstt_public_key → connects immediately.

Expected behavior

Whichever public key the project ships/exports for clients must match the private key the service actually uses.

Environment

  • Hiddify Manager: 12.3.3
  • OS: Ubuntu 24.04, kernel 6.8
  • DNSTT domain mode, tunnel service hiddify-dnstt-<domain>.service

Suggested fix

Derive server.pub from the same private key the unit is rendered with (or regenerate it whenever run.sh is rendered), or drop the server.pub / PUBLIC_KEY_FILE mechanism entirely and expose only hconfig dnstt_public_key as the client-facing key.

Workaround for users

Always hand clients hconfig dnstt_public_key; never other/dnstt/server.pub.

Related

  • #5363 and duplicates (#5385, #5464, #5381) — same DNSTT feature, different defect (subscription parse error). Between the two, DNSTT currently fails in two different ways before a client can even use it.