[EXPERIMENTAL FEATURE]
Adds an optional intermediate fallback hop through an external MTProto proxy when WebSocket fails, before resorting to direct TCP. Also documents the feature and the common dd-prefix footgun.
Fallback chain
WS → upstream MTProto proxy (new) → direct TCP (last resort)
Both the WS-failure path and the DC-not-in-config path attempt upstreams before falling through.
Changes
crypto.rs
- New
generate_client_handshake(secret, dc_idx, proto) → ([u8;64], enc_cipher, dec_cipher)— builds a valid 64-byte MTProto obfuscation handshake our proxy sends as a client to the upstream, with SHA-256 key derivation using the upstream's secret.encis fast-forwarded 64 bytes;decis not (mirrors the upstream's clt_enc/clt_dec pair).
config.rs
MtProtoProxy { host, port, secret }struct +parse_mtproto_proxy(right-splitsHOST:PORT:SECRET, hex-validates secret at parse time).--mtproto-proxy HOST:PORT:SECRETCLI flag (repeatable) /TG_MTPROTO_PROXYenv var (comma-separated).
proxy.rs
connect_mtproto_upstream— TCP connect with timeout, callsgenerate_client_handshake, sends handshake, returns split stream + ciphers.bridge_mtproto_relay— bidirectional re-encrypted bridge; reusesConnectionCipherswithtg_enc/tg_decset to upstream session ciphers.- Per-upstream 60 s cooldown keyed by
host:portto skip dead upstreams without stalling every connection.
main.rs
- Startup banner lists configured upstream proxies.
README.md
- Updated flow diagram, options table, env-vars section.
- New Upstream MTProto proxy fallback section with usage examples.
- ⚠️ Warning: public proxy secrets are prefixed with
dd— that prefix must be stripped before passing to--mtproto-proxy.