TLS: randomize padding, fix ALPS codepoint, optional ECH policy#30528
TLS: randomize padding, fix ALPS codepoint, optional ECH policy#30528RsNest wants to merge 3 commits intotelegramdesktop:devfrom
Conversation
|
sounds good, but codebase is so large... |
But fixed 512 padding is the default behavior for small packets. It won't be difficult to check the range 496-536 for them, such packets are much rarer and may cause even more questions. May be it's a half-measure, but not a solution imo
dump from the latest Chrome version: 17613 = 0x44CD |
Thanks. On S1, fair point: the current randomized floor is meant only as a minimal measurable step to remove a constant-length signature, not as a final indistinguishability solution. I can clarify that in the PR and keep stronger profile/capture-driven sizing for a follow-up step. On the ALPS point, could you clarify the codepoint expectation? The comment mentions 0x4469, but the dump snippet below shows 17613 (0x44CD), so I want to make sure I align with the exact wire format you expect. |
|
I already tested the change in captures: there is no malformed packet output in Wireshark, the TLS record is parsed correctly, and the resulting ClientHello/application data lengths are no longer constant between connections. |
You say that 0x44CD is legacy, but the ClientHello dump from the latest Chrome version shows that its still in use |
|
Let's use 44CD - with that TG JA4 hash is equal with latest (146) Chrome |
| # https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | ||
|
|
||
| option(TDESKTOP_BUILD_MTPROTO_TLS_TESTS "Build test_mtproto_tls_hello wire checks." OFF) | ||
| option(TDESKTOP_TLS_ECH_DEFAULT_OFF "Synthetic TLS: omit ECH by default (conservative egress)." OFF) |
There was a problem hiding this comment.
This looks useless. All browsers go into ECH, now you want to make it optional (who is going to build it with non-default option anyway?) making the code more complicated without any reason.
There was a problem hiding this comment.
Thanks, fair point.
I'll remove the default-off ECH option and keep ECH enabled by default.
And yes, separating the ClientHello refactor from the actual wire-format changes makes sense — I'll split that into a separate commit to make the review easier.
There was a problem hiding this comment.
I really advice to maintain PR's scope as little as possible and avoid refactors, especially if you're using AI (which it seems you do).
There was a problem hiding this comment.
Also, if you're using AI, prevent it from adding compile-time/env-based settings. That's not used by tdesktop. Ideally such things shouldn't be configured by the user. But if it's absolutely necessary, then use the experimental settings mechanism (base::option).
There was a problem hiding this comment.
Thanks, got it. I'll keep that in mind.
Either do it in a separate commit so that the changes are reviewable or maybe it would be even better to not do it at all |
| # For license and copyright information please follow this link: | ||
| # https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL | ||
|
|
||
| option(TDESKTOP_BUILD_MTPROTO_TLS_TESTS "Build test_mtproto_tls_hello wire checks." OFF) |
There was a problem hiding this comment.
Use already existing DESKTOP_APP_TEST_APPS
Replace the fixed 513-byte padding target with a per-connection random value in [512, 562]. Keeps the minimum above the 511-byte F5 device threshold while removing a constant-length DPI signature.
Replace fixed 2878-byte TLS application data record cap with a per-record random value in [2048, 4095]. This removes a constant record-size pattern observable by DPI.
|
Hmm, this changes the same place as #30513 but in other way. I wonder which one is right? |
|
Yeah, I meant #30513 |
After looking at the info from their TG channel, this PR looks more correct, because there are enough problems fixed(like Malformed Packets) + mimicry for a real browser (Chrome). Quite a lot of people have tested this PR and offered their fixes to it |
Buffer encrypted MTProto packets at the TcpConnection layer and flush them together after a random 5-30ms delay. This merges multiple small MTProto messages into fewer, larger TLS Application Data records, eliminating the characteristic burst pattern where several packets are sent within milliseconds of each other. File transfer connections bypass coalescing to preserve throughput. The connection nonce (first packet) is always sent immediately.
|
I'm probably dumb, but can the padding mathematically happen? If ClientHello includes X25519MLKEM768 key of 1216 bytes, it mathematically cannot fit into 512..562 bytes total. In the wild, I never seen padding in PQ-enabled browser, so wondering what exactly we are mimicking with 512..562 padding |
|
@SagePtr you're right, client hello here is always more than a KB, so those small paddings are irrelevant. To author and guys around, please stop vibecoding changes to protocol implementation without deep understanding. This won't end well. |
We are trying to build a more resilient client with our own hands because the official Telegram community has done almost nothing to actually help people in Russia deal with blocking and DPI. |
I think you're right about the overall size. With X25519MLKEM768 enabled, ClientHello is already much larger than 512..562 bytes, so that old target no longer really applies in PQ-TLS scenarios. |
|
Isn't a fail-fast approach much more favorable here than do-nothing? I suppose it's better to help the guys from Digital resistance |
Please do something. This process is becoming irreversible.
|
i fully agree and get it - as "maintainer to maintainer": but i don’t think this means people shouldn’t use ai at all, |
|
@avbor sure the availability without proxies / vpn is dying, they banned the endpoints. But this doesn't have anything to do with this PR. The "2-byte fix" really fixed working through myproxy, which is best you can expect right now. I hope we will be able to keep it working through unbanned mtproxies. |
|
That’s not entirely accurate. |
DPI currently doesn't ban MTProto servers, as it did in 2018. Currently, DPI simply detects Telegram traffic based on known signatures and doesn't allow it. My MTProto servers connect perfectly with version 6.7.2 clients, but they don't work with earlier versions. |
|
@1koh I believe that main official endpoints are still banned by IP, there is no sense in not doing that. |
Yeap, that is correct. And yes, the only truly effective strategy is the use of proxies. |
We can't solve the IP blocking issue with the main official endpoints. But we can ensure client-MTProto connectivity. We host MTProto proxies in locations where there is connectivity to official Telegram endpoints. |
The graph shows that unavailability began towards the end of march, these are the usual IP bans that have nothing to do with mtproto blocking. It's still easier for people to turn on vpn and use telegram without a proxy (especially on mobile devices). Yes, there were some problems with ClientHello, due to which DPI detected the proxy with minimal effort, but they were solved. |
We are here to discuss MTProto detection, not ip bans, which have nothing to do with this topic, because nothing can be done about them. Proxies are now working as before, but the plot won't get any better |
I will try to summarize somehow: The presented graph shows the availability of telegrams without bypassing blocks. Indeed, the main servers are banned by IP address. The previous patch was a solution to the problem of blocking MTPROTO proxies by a characteristic fingerprint when establishing a TLS connection, and it has nothing to do with blocking IP addresses, as other services on IP addresses with proxies were working.
I do not speak English, so I translated it using a translator. |
Did you try to read the code you are fixing and figure out under which circumstences what branches are executed? The padding is applicable only if entire ClientHello is between 256 and 512 bytes. This can never happen mathematically in this case. Also, isn't the goal of FakeTLS to mimic existing browser behavior in order to be as indistinguishable from them as possible, rather than inventing custom randomly sized padding schemes which are not used by any of real browsers and are therefore easy to detect? |
Not at all. Right now, for the vast majority of people, nothing is working. Where are the Android and iOS releases? |
The graph shows Telegram traffic. The MTProto proxy masks the traffic behind a fake SNI using Fake-TLS. It's no surprise that this graph doesn't show traffic passing through the MTProto proxy. All my MTProto proxies have been running for almost two months and haven't been banned by IP yet. |
what does this have to do with this PR and our topic? It seems to me that it's time to stop offtopic, the discussion is overheated, its a pull request about mtproto first of all and not about the availability of telegram in general |
I appreciate the detailed review. The padding change was a mistake on my side — I didn’t verify which code path actually runs with the current PQ ClientHello. I’m not trying to push random protocol tweaks; I’ll fix my own oversights, incorporate this feedback, and push an updated revision shortly rather than arguing around it. |
Let's be fair, this stance isn't entirely correct. 99% of the work was done half a year ago, in b72deb1 (updating to that time's actual Chrome client hello). Other clients should have similar commits since they all did it based on some internal document of their specialist. Yeah, they made bugs in two lines but who and how would find them before TSPU rules were deployed? The community (not only the telemt one!) has made a good reasearch and that's a very good thing but still the PRs provided were of a bad quality: fixing one bug, introducing a new one. It's entirely unfair to say that Telegram has done nothing and everything was done by telemt community as it's told on habr and I guess meant by you. What really happened is: Telegram has made a big fix with a bug in two lines half a year ago, the community has done a good research, attempted to fix code but failed yet the research helped the devs to fix the initial bug. Everyone has done something. |
Я понял ваш посыл, и в целом понял позицию всех, кто здесь писал. Повторюсь: мы не рассчитывали, что PR примут в первый же день, и в целом не ожидали моментального аппрува. Нам скорее хотелось получить обратную связь от разработчиков Telegram: двигаемся ли мы вообще в правильную сторону, насколько можно и нужно менять кодовую базу, и имеют ли смысл такие небольшие, не критичные изменения. Вы посчитали эти изменения бесполезными или ненужными — мы это тоже услышали и учли. Самое важное, что мы получили из этой дискуссии — это мысль Preston о том, что сначала нужно чётко понять, какую именно проблему мы пытаемся решить, и как вообще определить, что она действительно решена. Моя задумка, как и задумка сообщества telemt, была в том, чтобы подтолкнуть команду к изменениям, которые могут сделать клиент стабильнее и устойчивее. Что касается изменений, которые Telegram сделал полгода назад — тех самых двух строк: а какой практический результат они дали? Стал ли мессенджер действительно устойчивее? Не вижу особого смысла сейчас выяснять, кто прав, а кто виноват. Мы получили огромный объём обратной связи, и это уже очень важно. Спасибо. |
Hi-Angel
left a comment
There was a problem hiding this comment.
I just tested this PR and it fixes a critical bug of Telegram desktop no longer being able to connect to any proxy — a problem that started 3-4 hours ago.
Currently, Android Telegram works fine with proxy, however desktop telegram (with the same proxy) hangs infinitely trying to connect. That's with latest 6.7.5.
This branch fixes the problem.
Hi! I’m also using a custom Telegram Desktop build with my own fixes, and everything works fine for me on desktop Telegram with proxies. |
|
The fix actually works, Telegram is back to life. |
|
@RsNest, could you share your build? None of the proxies are working for me today. |
|
@anton-tagunov here's mine, it's an Archlinux package. |
|
@Hi-Angel thank you, but I am виндузятник. :-( Has anybody built the fork for Windows? I can try to do it tomorrow only. |
|
As of ½ an hour ago the PR it seems no longer works. Like, there's a public proxy I can access with netcat |
|
Okay, some proxies just started working… but not the one I pointed to in particular, so something may still be going on. |
DPI doesn't sleep 🫠 |
Yeah, I understand, but DPI uses heuristics in attempts to distinguish MTProto from usual sites traffic, and your PR supposed to make MTProto more indistinguishable from such traffic, which means there's something else in the traffic that DPI can cling to. Anyway, every bit matters, so I'll be very happy once you address the feedback and your commits will become part of the mainstream Telegram 😊 |







Summary
Hardens the synthetic TLS transport (MTProxy ee fake-TLS) against static DPI fingerprinting by removing constant-size signatures and eliminating characteristic burst patterns.
Changes
Padding (S1): Replace fixed 513-byte ClientHello padding target with a per-connection random value in [512, 562], staying above the 511-byte F5 device threshold.
Record size (S5): Replace fixed 2878-byte application data record cap with a per-record random value in [2048, 4095], so bulk transfers no longer produce a constant chunk-size pattern.
Packet coalescing: Buffer encrypted MTProto packets at the TcpConnection layer and flush them together after a random 5–30 ms delay. This merges multiple small messages into fewer, larger TLS records, eliminating the burst pattern where several packets are sent within milliseconds of each other. File transfer connections bypass coalescing to preserve throughput.
Testing
Built locally on Windows (Debug, MSVC v143); verified app runs and connects.
Wireshark captures confirm varying TLS record lengths during data transfer.
Wireshark captures confirm coalesced packets: individual chat messages that previously produced separate TLS records now appear as single, larger records (e.g. 738, 1120 bytes vs typical 200–450 bytes per message).
No UI changes, no new files, no new build flags.