Ограничение HTTP/3 (QUIC)

Есть еще одна мысль. Недавно такая проблема вскрылась.
Если в linux настроен сложный policy routing. Несколько аплинков, таблиц маршрутизации, ip rule , основанные на source address, то пакеты, высланные через raw socket-ы могут уходить не с того интерфейса. Что от nfqws, что от nping. При этом обычные пакеты уходят нормально.
Если это ваш случай, то надо убедиться, что пакеты идут действительно в нужный интерфейс и правильно заменяется source адрес , если используется NAT.
Пока что самое эффективное лечение этой ситуации - вносить ip rule, базированные на fwmark, который выставляет nfqws

Skynet, СПб
Блочится http3 до инстаграмма и фейсбука, но до гугла пропускает. Похоже стали расшифровывать заголовки.
Причем по http2 пропускает тоже. К слову у skynet нет dpi, блок идет на транзитном провайдере, скорее всего МТС

http3 до инсты

./curl -4Iv -m 5 --http3 https://instagram.com
*   Trying 31.13.72.174:443...
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* Connect socket 5 over QUIC to 31.13.72.174:443
* Sent QUIC client Initial, ALPN: h3,h3-29,h3-28,h3-27
* After 2493ms connect time, move on!
* connect to 31.13.72.174 port 443 failed: No error
* Failed to connect to instagram.com port 443 after 2507 ms: Couldn't connect to server
* Closing connection 0
curl: (28) Failed to connect to instagram.com port 443 after 2507 ms: Couldn't connect to server

http3 до инсты через vpn

./curl -4Iv -m 5 --http3 https://instagram.com
*   Trying 31.13.72.174:443...
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* Connect socket 5 over QUIC to 31.13.72.174:443
* Sent QUIC client Initial, ALPN: h3,h3-29,h3-28,h3-27
*  subjectAltName: host "instagram.com" matched cert's "instagram.com"
* Verified certificate just fine
* Connected to instagram.com () port 443 (#0)
* h2h3 [:method: HEAD]
* h2h3 [:path: /]
* h2h3 [:scheme: https]
* h2h3 [:authority: instagram.com]
* h2h3 [user-agent: curl/7.83.0-DEV]
* h2h3 [accept: */*]
* Using HTTP/3 Stream ID: 0 (easy handle 0x560fda7c27d0)
> HEAD / HTTP/3
> Host: instagram.com
> user-agent: curl/7.83.0-DEV
> accept: */*
>
< HTTP/3 405
HTTP/3 405

http2 до инсты

./curl -4Iv -m 5 --http2 https://instagram.com
*   Trying 31.13.72.174:443...
* Connected to instagram.com (31.13.72.174) port 443 (#0)
* ALPN: offers http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN: server accepted http/1.1

http3 до гугла

./curl -4Iv -m 5 --http3 https://google.com
*   Trying 64.233.162.100:443...
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* Connect socket 5 over QUIC to 64.233.162.100:443
* Sent QUIC client Initial, ALPN: h3,h3-29,h3-28,h3-27
*  subjectAltName: host "google.com" matched cert's "google.com"
* Verified certificate just fine
* Connected to google.com () port 443 (#0)
* h2h3 [:method: HEAD]
* h2h3 [:path: /]
* h2h3 [:scheme: https]
* h2h3 [:authority: google.com]
* h2h3 [user-agent: curl/7.83.0-DEV]
* h2h3 [accept: */*]
* Using HTTP/3 Stream ID: 0 (easy handle 0x55ae3ae897d0)
> HEAD / HTTP/3
> Host: google.com
> user-agent: curl/7.83.0-DEV
> accept: */*
>
< HTTP/3 301
HTTP/3 301

Они писали на форуме, что на разных тарифах разные фильтры стоят. На lite “более сильный DPI”
А может быть от адреса подключения зависит
У меня тариф “Земля”. Все нормально и по v4, и по v6

Разработчики СКАТ DPI (VAS Experts) выпустили статью о работе с QUIC в своём блоге.

На мобильном мегафоне возможно тоже такое есть: пришлось сменить симку в модеме на сим с другим тарифом, и прошлые настройки zapret перестали работать

Kathrin Elmenhorst, an author of “Web Censorship Measurements of HTTP/3 over QUIC”, has a repository with further tests of QUIC blocking, derived from OONI measurements. One thread of investigation is about Russia, and it has some interesting observations.

In particular, on Yota (AS 31213), there appears to be a two-layer filter. One layer blocks all QUIC version 1, except to specific servers; and a second layer blocks QUIC version 1 with with specific SNI values, no matter the server. This is interesting because the second layer means they are decrypting the initial packet protection on the packet containing the Client Hello.

The evidence for this comes from observing what happens when accessing different servers using different SNI values.

condition result
Access foreign server with correct SNI blocked
Access foreign server with vk.com SNI blocked
Access vk.com server with vk.com SNI works
Access vk.com server with www.facebook.com SNI blocked

Всё ещё наблюдается?
Сколько пакетов пропускает до блокировки (на картинке сквозная нумерация, число неочевидно)? Сохранились дампы?

Наблюдается. Там хаотичное поведение. 1-2 сессии могут пройти, 3 - застрять
сколько пакетов я не считал
2 провайдера с ТСПУ дают одинаковое поведение

Система может расшифровать QUIC_V1 и декодировать SNI.

Если ограничиться тестовым набором или соблюдать тестовые размеры, тогда всё работает: SNI декодируется и принимается решение.

Система не может или не хочет достать SNI из пакета, который генерирует Firefox. Возможно дело в размерах (например для структур далее по стеку). Недоступный SNI триггерит блокировку.

Приведите пример пакетов, которые фильтруются и не фильтруются. Выложите pcap’ы или содержимое пакетов.

blocked_firefox.bin (1.3 KB)
works_quictls.bin (1.2 KB)

Еще раз проверил на своем провайдере с ТСПУ
Ничего не поменялось. Нет никаких признаков в пользу предположения о декодировании SNI
Действительно, blocked_firefox.bin не проходит, а works_quictls.bin проходит
Оба они от example.com. Подозреваю, там стоит фильтр по некоторым полям или длинам без декодирования, который почему-то не срабатывает в одном случае
Пробовал curl с quiche на свой vps с разными SNI, в том числе vk.com. Ничего не проходит
На белосписочные IP от vk проходит все

./curl -4 --connect-to ::vk.com:443 --http3 https://example.com
curl: (55) SSL: no alternative certificate subject name matches target host name 'example.com'

При пробивании нулевым фейком или пакетом works_quictls.bin идентичное поведение. Хаотичный вис при загрузке сайтов

facebook_quictls.bin (1.2 KB)
Этот проходит?

Есть, как минимум, проверка целостности: если изменить хоть один байт в works, то пакет не доходит.
Планирую провести детальные исследования, но если кто-то готов перехватить эстафету, буду только рад.

Нет

Значит, все же расшифровывают. В QUIC initial нет никаких контрольных сумм, там используется GCM для аутентификации. Это AEAD шифр. Authenticated Encryption with Associated Data.
Шифрование и аутентификация завязаны в том числе и на нешифрованный хедер, чтобы любое изменение порождало неверный atag. И только полная дешифровка с проверкой atag позволяет отсечь коррупцию в любом байте пакета.
Однако, в остальных предложенных вариантах с этим тоже все в порядке.
Значит они или ориентируются на расшифрованный блок (почему не секут тогда SNI ?), или расшифровывают исключительно для проверки целки, а блочат по другим признакам типа длины
Или может быть в некоторых случаях они могут просечь SNI и блочат по нему, а в других случаях не могут (несовершенство парсера дешифрованного блока ?) и блочат, если IP не в white list
nfqws может распарсить все предложенные бинарики

Воспроизводится для гугла при запросе из curl+quictls, не воспроизводится для запросов из Firefox. (Внешнее различие в размерах пакетов, у Firefox они больше, а гугл-сервер в выборе размера пакетов ориентируется, в том числе, на размер QUIC initial клиента.)

До принятия решения о блокировке проходит в среднем 15 входящих пакетов. (Возможно применяется скользящее окно, поэтому не следует ориентироваться на число пакетов с начала сеанса). Выглядит как статистический анализ? Ложно триггерит правило блокировки psiphon или иного протокола (не связанного с QUIC)?

Не понятно столь широкое применение правила, возможно есть ограничение на адреса/порты/паттерны_inside.

This.

Возможно SNI успешно извлекается везде, а за блокировку по неизвестным паттернам из расшифрованного QUIC initial отвечает другое правило.

Можно сравнить пакеты от Firefox, quictls и quiche.
В коллекцию следует добавить legal_sni_quiche.bin

Возможно используется отложенный процессинг. Расшифровка - задача потенциально тяжелая
Видим initial, временно разрешаем, отдаем в отдельный поток, когда поток возвращает результат - принимаем решение.
Отдельный поток может ориентироваться на текущую загрузку DPI и отказываться от тяжелых операций при необходимости

Заполнение нулями (наружное) QUIC initial триггерит блокировку. В Firefox такое применяется. В quictls внутренний с финальными 1200 байтами. В quiche – у меня нет данных (не собирается ржавчина).

Хаотичные зависания могут быть вызваны большими (1400+) QUIC пакетами в середине сеанса, которые триггерят блокировку. В моем случае это был механизм pmtud на QUIC клиенте, после отключения зависаний нет. К проблемам с mtu это не имеет отношения, блокировка по тестируемым парам адреса:порты наблюдается на хопе с ТСПУ.

У Firefox нет механизма pmtud, но он может быть на сервере.

UPD:
Большой размер пакета похоже так не важен, дело в другом.

Есть скрипт, который возможно воспроизводит блокировку.

Активация блокировки:
Запрос, ответ, запрос.
Нет ответа – нет блокировки.
Размер запросов и ответа учитывается, но точно неизвестно.

UPD: Код бредовый. Удалил. Вызывает блокировку потому что нарушает RFC.