Фильтр TLS на домены youtube

Раз уже понятна схема блокировки, остался один вопрос: зачем так геморно и с таким паттерно? Почему нельзя просто заблочить по SNI? Или это специально для андроид клиента?

Right now it seems like a TLS Fingerprinting to block an Android application which uses www.youtube.com as a domain fronting (wild guess: Navalny Android/iOS app?).

Seems, NewPipe’s fingerprint is quite unique. https://tlsfingerprint.io/ does not parse Client Hello from aforementioned pcaps as known fingerprint that was already observed in the campus traffic.

Its really useless to block NewPipe. Best candidate to block is Google’s Youtube app. Can it be something like tests or preparations for whole youtube block?

I have no iOS devices, but Navalny’s app (ver. 2.0, one from Google Play Market) gives a different fingerprint on my Android:

Fingerprints https://tlsfingerprint.io/id/f0b2b996867b6380 and https://tlsfingerprint.io/id/f278257cdf4a43aa seem to be related, cetpmhjmdf-vizskfsved.global.ssl.fastly.net is Navalny-related domain (see https://archive.md/xgT57 for archived content).

They use okhttp3 library with ConnectionSpec.MODERN_TLS.cipherSuites() and 2 additional ones click

// This will try to enable all modern CipherSuites(+2 more)
// that are supported on the device.
// Necessary because some servers (e.g. Framatube.org)
// don't support the old cipher suites.
// https://github.com/square/okhttp/issues/4053#issuecomment-402579554
final List<CipherSuite> cipherSuites =
        new ArrayList<>(ConnectionSpec.MODERN_TLS.cipherSuites());
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
final ConnectionSpec legacyTLS = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
        .cipherSuites(cipherSuites.toArray(new CipherSuite[0]))
        .build();

builder.connectionSpecs(Arrays.asList(legacyTLS, ConnectionSpec.CLEARTEXT));

UPD

UPD: no, they use this cipher set only in this exact case, but in general they have a common okhttp3 cipher list (without 3DES, it is probably filtered by the tls library): okhttp/okhttp/src/main/java/okhttp3/ConnectionSpec.java at 06644bb0507873e9a3b89d9107da537f1b140e91 · square/okhttp · GitHub

I’ve made a small modification in NewPipe by replacing TLS_RSA_WITH_AES_256_CBC_SHA with TLS_RSA_WITH_AES_128_CBC_SHA in the library cipher list, and the application is now working again.

SmartTubeNext тоже перестал работать, по крайней мере, с теле2.

UPD: no, they use this cipher set only in this exact case, but in general they have a common okhttp3 cipher list (without 3DES, it is probably filtered by the tls library): okhttp/okhttp/src/main/java/okhttp3/ConnectionSpec.java at 06644bb0507873e9a3b89d9107da537f1b140e91 · square/okhttp · GitHub

So they block HTTPS requests to www.youtube.com via okhttp library.

Hint: this block could be circumvented by changing SNI case. wWw.youtube.com works.
Hint: other domains, such as docs.google.com, are not blocked with this TLS fingerprint.

Фильтр убран. Что это такое было — непонятно, у меня нет даже предположений.

Я тут на днях поизучал последнюю версию приложения Навальный. Okhttp обнаружить не смог. Более того, оно максимуи, что пытается сделать, так это обратится к DnS.GooGle и, вроде как, не использует домены youtube. Блокировки пытается обойти через newnode, а это битторенты и прочие данные по udp протоколу. Соответственно, эта приложуха тут не причем.
При всем при этом, очевидно, это не случайный фильтр и для чего-то он тестировался. Осталось понять, зачем? Другой вопрос, что фильтр убрали, когда гугл согласился сотрудничать и удалить видео с канала Навального, только причем тут newpipe, который, так и так, мало кто использует, а те, кто используют, знают про VPN?

У меня два предположения, высосанных из пальца:

  1. Проводилась демонстрация возможности блокировки конкретной программы, а не сервиса: «Смотрите, в браузере работает, в официальной программе работает, а в NewPipe — не работает».
  2. Перепутали NewNode и NewPipe.

I had a quick look at an APK I found at https://www.apkmonk.com/download-app/com.navalny.blog/4_com.navalny.blog_2021-08-15.apk/ (version 2.0, dated 2021-08-14).

  1. There are many references to “OkHttp” in the code. I see okhttp3. which matches the major version reported earlier; however there is also okhttp/4.6.0. (Well, looking at the changelog, it seems these numbers do not have to match and okhttp3 is the correct package name even for later versions.)
  2. In the disassembled code (smali/s/k.smali), there is a list of 4 strings:
    {"dns.google", "1.1.1.1", "1.0.0.1", "doh.opendns.com"}
    
  3. The string youtube does not appear.
$ apktool d com.navalny.blog_2021-08-15.apk
$ cd com.navalny.blog_2021-08-15

$ grep -ir okhttp
smali/io/ktor/client/engine/okhttp/OkHttpEngineContainer.smali:.class public final Lio/ktor/client/engine/okhttp/OkHttpEngineContainer;
smali/io/ktor/client/engine/okhttp/OkHttpEngineContainer.smali:    const-string v0, "OkHttp"
smali/n/b/k/a.smali:    const-string v4, "OkHttp"
smali/o/y.smali:    const-string v0, "null cannot be cast to non-null type kotlin.collections.List<okhttp3.Interceptor?>"
smali/o/y.smali:    const-string v1, "okHttpClient"
smali/o/i0/c.smali:    const-string v2, "OkHttpClient::class.java.name"
smali/o/i0/c.smali:    const-string v2, "okhttp3."
smali/o/i0/h/e.smali:    sget-object v2, Lokhttp3/internal/publicsuffix/PublicSuffixDatabase;->d:Lokhttp3/internal/publicsuffix/PublicSuffixDatabase$a;
smali/o/i0/h/e.smali:    sget-object v2, Lokhttp3/internal/publicsuffix/PublicSuffixDatabase;->c:Lokhttp3/internal/publicsuffix/PublicSuffixDatabase;
smali/o/i0/h/e.smali:    invoke-virtual {v2, v5}, Lokhttp3/internal/publicsuffix/PublicSuffixDatabase;->a(Ljava/lang/String;)Ljava/lang/String;
smali/o/i0/h/a.smali:    const-string v11, "okhttp/4.6.0"
... many more ...

$ grep -ir -F -A 32 dns.google
smali/s/k.smali:    const-string v7, "dns.google"
smali/s/k.smali-
smali/s/k.smali-    invoke-direct {v6, v7, v4}, Li/g;-><init>(Ljava/lang/String;Lb/a/a/e;)V
smali/s/k.smali-
smali/s/k.smali-    aput-object v6, v5, v21
smali/s/k.smali-
smali/s/k.smali-    new-instance v6, Li/g;
smali/s/k.smali-
smali/s/k.smali-    const-string v7, "1.1.1.1"
smali/s/k.smali-
smali/s/k.smali-    invoke-direct {v6, v7, v4}, Li/g;-><init>(Ljava/lang/String;Lb/a/a/e;)V
smali/s/k.smali-
smali/s/k.smali-    aput-object v6, v5, v20
smali/s/k.smali-
smali/s/k.smali-    new-instance v6, Li/g;
smali/s/k.smali-
smali/s/k.smali-    const-string v7, "1.0.0.1"
smali/s/k.smali-
smali/s/k.smali-    invoke-direct {v6, v7, v4}, Li/g;-><init>(Ljava/lang/String;Lb/a/a/e;)V
smali/s/k.smali-
smali/s/k.smali-    const/4 v7, 0x2
smali/s/k.smali-
smali/s/k.smali-    aput-object v6, v5, v7
smali/s/k.smali-
smali/s/k.smali-    new-instance v6, Li/g;
smali/s/k.smali-
smali/s/k.smali-    const-string v7, "doh.opendns.com"
smali/s/k.smali-
smali/s/k.smali-    invoke-direct {v6, v7, v4}, Li/g;-><init>(Ljava/lang/String;Lb/a/a/e;)V
smali/s/k.smali-
smali/s/k.smali-    const/4 v4, 0x3
smali/s/k.smali-
smali/s/k.smali-    aput-object v6, v5, v4

$ grep -ir youtube

The filter was configured for SNI check. It wasn’t IP-bound.
I also edited SNI in the captured packet to docs.google.com, and it was delivered successfully. Haven’t tried other SNIs.

Проблема с NewPipe встречалась мне только один раз.

Регулярно встречаю ошибки буферизации при воспроизведении Ютуба с помощью mpv + youtube-dl со следующими ошибками в командной строке:

    ffmpeg: tls: Error in the pull function.
    ffmpeg: https: Will reconnect at 262144 in 0 second(s), error=Input/output error.

Получается, ffmpeg тоже блокируют.

А патченная версия NewPipe от ValdikSS’a не пишет ли куда-либо обширные логи ? Смущает слово"debug" в названии. Отладка в данном вопросе дело конечно нужное, но для меня этот фикс проблему решил и хотелось бы обойтись без лишних логов, которые будут захламлять память.

The APK at GitHub claims to be v2.2 and it mentions www.youtube.com. But the TLS fingerprint of the traffic produced by that APK is slightly different from NewPipe’s fingerprint as well. I take NewPipe’s fingerprint from the aforeposted pcaps.

v2.2 from apkmonk also mentions youtube, but the binary differs from GitHub release.

Thanks, great find. I confirm that I find “www.youtube.com” in the 2.2 APK.

smali/s/k.smali:    const-string v11, "www.youtube.com"

Also, the list of DNS resolver names removes “1.1.1.1”.

{"dns.google", "1.0.0.1", "doh.opendns.com"}

v2.2 from apkmonk also mentions youtube, but the binary differs from GitHub release.

For me, the two binaries are the same.

$ sha256sum *.apk
58913378ea52b6effa28117f201ae73f4ae473fd2aa965627f7b1c07b4350c20  androidApp-release-69_2-2.apk
58913378ea52b6effa28117f201ae73f4ae473fd2aa965627f7b1c07b4350c20  com.navalny.blog_2021-09-14.apk

Indeed, my bad. Seems, I’ve confused the apk from apkmonk with the v2.2 apk from apkcombo.com having sha256 3a2dc36dcaac20e8d52ac91b6290508a3c3209dc4bd81f91b86924304122c699.