Случайная блокировка игры SCP Secret Laboratory на ТСПУ по UDP протоколу

Предыстория

С сентября 2023 года, игроки массово (не по всей стране сразу) с разных регионов и с разных провайдеров стали жаловаться на невозможность зайти на любой игровой сервер в игре SCP Secret Laboratory, это происходило практически в одно и тоже время, но точно в один день, это различные волны блокировок, которые касаются не всех и не сразу, у некоторых блокировка пропадает спустя несколько дней, а у кого-то она и вовсе не пропадает:

Видео:

Владельцам серверов буквально пришлось рекомендовать использовать VPN игрокам, которые не могли зайти на сервера, и это помогало, сами же разработчики игры стали советовать тоже самое.

Техническая часть

Игра сделана на Unity, используется сетевой движок Mirror, транспорт LiteNetLib. В игре есть список серверов, он работает по HTTPS, с этим никаких проблем нет, проблемы начинаются только непосредственно при попытке подключится на сервер по UDP, сервер успевает отправить клиенту команду на загрузку сцены Assets/_Scenes/Facility.unity, а далее соединение уже блокируется на ТСПУ.

Дампы с блокировкой соединения:
packet_loss_from_client.pcapng (6,3 КБ)
TSPU block scp secret laboratory.pcapng (14,3 КБ)

Дамп, где соединение проходит нормально используя VPN:
scp sl normal connection.pcapng (552,1 КБ)

Сетевой движок игры может переотправлять UDP пакеты, если они не дошли до сервера, в дампах же видно большое количество переотправленных пакетов:

Диагностика

Некоторые владельцы серверов стали почему-то считать, что это баг игры или какая-нибудь ddos атака на сервер, но это не так. Мне удалось договорится с одним игроком(у которого соответственно имеется эта проблема в виде блокировки), чтобы он у себя развернул виртуальную машину на базе VirtualBox, где уже был заготовлен OpenVPN сервер, потому что этой блокировки не было на ТСПУ в моём регионе. Далее я подключился к этому OpenVPN серверу и сделал трассировки для выявления хопа с ТСПУ:


(Трассировка по ICMP до заблокированного IP-адреса на ТСПУ)

(Трассировка по UDP до любого не заблокированного IP-адреса на ТСПУ)

ТСПУ идёт после хопа 10.210.116.18, виден как при трассировке по ICMP, так виден и при трассировке по UDP, какой-либо балансировки с IP-адресами по трассировке в сети провайдера я не увидел.

Я решил с помощью iptables модифицировать TTL прямо в моменте соединения к серверу, и в дампах видно отсутствие ICMP TTL Exceeded пакетов от IP-адресов, которые находятся за пределами ТСПУ, пакеты не выходили за пределы сети провайдера:
modify_ttl.pcap (6,9 КБ)
modify_ttl_1.pcap (6,7 КБ)
modify_ttl_2.pcap (6,8 КБ)
modify_ttl_3.pcap (6,6 КБ)
modify_ttl_4.pcap (6,5 КБ)
modify_ttl_5.pcap (6,5 КБ)
(При просмотре дампов обращайте внимание на поле TTL в IP заголовке)

Воспроизведение блокировки искусственным путём

В поисках паттерна, обнаружил, что самым главным условием является то, чтобы ответ от сервера был именно путь до загружаемой сцены Assets/_Scenes/Facility.unity и какой-то определённый ответ от клиента(который мне не удалось выявить), однако блокировка будет срабатывать, даже если ответ от сервера будет например Assets/Zfjdsjf/Sfjsdfij (вероятней всего используется какое-то регулярное выражение на основе regexp).
Запускаем на сервере netcat:

ncat -klu 7777 -v --sh-exec "echo -n 'Assets/_Scenes/Facility.unity'"

Со стороны клиента отправляем 5 пакетов с определённым содержимым с помощью nping:

nping --udp --data "0c0d0002000002010000000000000000200001000002755f29266a7071400fcba206000003000500070009001000039f8f00140000755f29266a7071400a7f81755f29266a707140" -c 5 -g 25591 -p 7777 X.X.X.X

Содержимое в --data был взят из дампа, пакет с таким содержимым высылает сам клиент игры.
После отправки 3-4-ёх пакетов, соединение блокируется на ТСПУ:

Решение проблемы

Владельцы серверов могут легко решить проблему, установив nfqws от zapret на сервер:

  1. Скачать на сервер nfqws - zapret/binaries/x86_64/nfqws at master · bol-van/zapret · GitHub
  2. Запустить его из под рута в tmux следующей командой: ./nfqws --qnum=250 --dpi-desync-any-protocol=1 --dpi-desync-repeats=20 --dpi-desync-fwmark=0x40000000 --dpi-desync=fake --dpi-desync-fake-unknown-udp=0x0726b1a36a672ddc080d0003a19b3902009020
    Payload пришлось подбирать специфичный, сетевой движок на клиенте может крашнутся, если он получит какой-либо пакет от сервера, который не связан с игрой, стандартный payload в виде нулей в этом случае не подойдёт.
  3. Добавить правило iptables: iptables -t mangle -A POSTROUTING -p udp -m multiport --sports 7777:7790 -m connbytes --connbytes 1:1 --connbytes-mode packets --connbytes-dir original -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 250 --queue-bypass (диапазон портов сменить, если он у вас другой)
  4. Это заставит сервер отправить 20 фейковых пакетов единоразово в сторону клиента, клиент эти пакеты проигнорирует, а затем уже будет отправлен исходный пакет от сервера, это решает проблему с ложной блокировкой игры со стороны ТСПУ.

Со стороны клиента так же помогает:

./nfqws --qnum=250 --dpi-desync-any-protocol=1 --dpi-desync-repeats=20 --dpi-desync-fwmark=0x40000000 --dpi-desync=fake
iptables -t mangle -A POSTROUTING -p udp -m multiport --dports 7777:7790 -m connbytes --connbytes 1:1 --connbytes-mode packets --connbytes-dir original -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 250 --queue-bypass

Серверу уже всё равно на стандартный payload в виде нулей, он от этого не крашается.

Исследование интересное, но:

Не замечал ни в одной игре никаких проблем при отправке стандартных фейков (нулей) запретом со стороны клиента (именно SCP не проверял, но в других сетевых играх такой проблемы нет).

20 фейковых пакетов это по-моему перебор, для обхода любых блокировок udp на данный момент хватает 6 фейков. Хотя конечно все зависит от провадера, но чтобы больше 6 фейков надо было пока не встречал.

Нули нельзя отправлять лишь только со стороны сервера клиенту, иначе на клиенте сетевой движок выпадет в exception и все игроки зависнут на месте лишь только визуально на клиенте, сетевой обмен перестанет работать. От клиента к серверу отправлять нули можно.

Да, согласен, но я перестраховался на всякий случай.

Чтобы такого не происходило впредь - посоветуйте разработчикам игры шифровать трафик :innocent:

Не думаю, что в этом есть какой-то смысл, к тому же ничего не исключает вероятность случайной блокировки и зашифрованного трафика. Шифрование трафика может сломать готовые правила для защиты от DDoS-атак на эту игру, особенно у Stormwall.

Когда-то обсуждал с разработчиком про шифрование голосового чата в игре, он написал что смысла от этого нет.

Заметил новое: если сервер будет возвращать просто набор букв Djasdjcxa/Jdhdashc/Jcxnduas, то соединение так же будет блокироваться.

Сервер:

ncat -klu 7777 -v --sh-exec "echo -n 'Djasdjcxa/Jdhdashc/Jcxnduas'"

Клиент:

nping --udp --data "0c0d0002000002010000000000000000200001000002755f29266a7071400fcba206000003000500070009001000039f8f00140000755f29266a7071400a7f81755f29266a707140" -c 5 -g 25599 -p 7777 X.X.X.X

А если сервер например будет возвращать fsdfdsff, то никакая блокировка и не будет происходить.

Соединение на ТСПУ может заблокироваться даже вот с таким отправленным пакетом со стороны клиента лол:

nping --udp --data "0c0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" -c 5 -g 23700 -p 7777 X.X.X.X

Главное чтобы при этом ответ от сервера был схожим на Assets/_Scenes/Facility.unity, например Djasdjcxa/Jdhdashc/Jcxnduas

Ещё схожее обнаружил, точно так же блокируется на ТСПУ:

nping --udp --data "0d000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" -c 5 -g 23709 -p 7777 X.X.X.X

Имелось в виду - если не будет сигнатур - по сигнатурам, случайно, уже не заблокируют.

Ну судя по тому, что я обнаружил выше, как-то сложно соотнести блокировку к какой-то сигнатуре в виде кучи нулей и рандомных английских букв.

Посмотрите последние сообщения в теме Блокировка шифра в сторону Cloudflare на ТСПУ - #32 by 0ka
Тоже ловили сигнатурой одно, а поймали другое…

В той теме блокировка происходила хотя бы на основе каких-то полезных данных в пакете, а тут соединение блокируется даже без какой либо смысловой и полезной нагрузки.
На сервере:

ncat -klu 7777 -v --sh-exec "echo -n 'Aaaaaaaaaa/aaaaaaaaa/aaaaaaaaa'"

На клиенте:

 nping --udp --data "0a0d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" -c 5 -g 23712 -p 7777 X.X.X.X

2-3 пакета и ТСПУ блокирует соединение.

Я не настоящий сварщик, но уверен, что ТСПУ “все равно”, есть в пакете полезная нагрузка или нет. Оно срабатыает либо по спискам адресов, либо по сигнатурам. В вашем случае, видимо, срабатывает сигнатура. Делать сложный анализ пакетов в массовом пордке - дорого, в терминах нагрузки на процессор, поэтому делают анализ максимально простым. В вашем слуае - сделали правило типа “если в запросе первые байты 0x0a0d, а в ответе 7 и 17 байты - буквы ‘а’ - заблокировать”. И в 99.9% случаев это срабатывает - блокируется только вредный, преступый, террористический трафик.

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

(Пишу это в основном для того, чтобы, если неправ, меня поправили настоящие сварщики.)

Там срабатывает на любые буквы вообще, возможно используется регулярка, не дорого ли для процессора делать регулярку в этом случае?

Ну зная, как “работают” разработчики этой игры, не думаю что они возьмут и на “ура” сделают это самое шифрование.

Возможно, содержимое не учитывают совсем или всё чуть сложнее. Блокировка воспроизводится для небольших датаграмм с рандомной нагрузкой. Исходящие размером 55-74 байт, входящие 20-100 байт. Схема: запрос-ответ. После 2-3 ответов следует блокировка.

Если отправлять только нули с размерами 55-74 байт со стороны клиента, 20-100 байт со стороны сервера, то блокировка не происходит.

Тут скорее всего всё в разы сложнее.

Блокировка воспроизводится даже вот так, без рандомных данных:
Сервер:

ncat -klu 7777 -v --sh-exec "echo -n '1110000000000000000000000000000000000000' | xxd -r -p"

Клиент:

nping --udp --data "11100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" -c 5 -g 23742 -p 7777 X.X.X.X

Наблюдение: Множество ТСПУ где сейчас блокируют (блокировали) XMPP пересекается с множеством ТСПУ блокирующих UDP пакеты из этой темы. Притом обе блокировки встречаются достаточно редко, примерно как ТСПУ в байпасе.

Из этого сообщения у меня команда openssl s_client -starttls xmpp-server -host xmpp.quicksy.im -port 5269 -xmpphost quicksy.im -servername quicksy.im </dev/null &>/dev/null && echo ok || echo fail выдаёт fail

EDIT: Прошу прощения, допустила ошибку при тестировании. Подтверждаю - у меня наблюдается и блокировка VPN, и блокировка XMPP, и блокировка по примерам из данной темы.

Еще, мне кажется что дело не в каком-то “множество ТСПУ”. У меня есть наблюдения, позволяющие полагать, что дело не в конкретных ТСПУ, а в неких черных списках. Предполагаю, что есть некие черные списки, в которые заносятся IP-адреса как источника (пользователей интернета), так и назначения (серверов в интернете). Заносятся они туда видимо по выявлении некой запрещенной активности, и по факту занесения туда коннекты от/к ним подвергаются более глубокому анализу.

Например, у меня сейчас наблюдается блокировка XMPP в сторону вышеупомянутого quicksy.im. Но в сторону моего личного сервера, коннекты к которому я некоторое время назад завернула в VPN и ТСПУ их не видит, блокировки сейчас нет, даже если выключить VPN.

При этом quicksy.im блочится с моего проводного провайдера, но работает через мобильную связь. Тут важно, что у меня статический IP у провайдера уже несколько лет.

Еще пример, я несколько лет активно пользуюсь OpenVPN, и с прошлой осени постоянно попадаю на блокировки. Сейчас наблюдаю блокировку перманентно уже на протяжении месяца. В то время как условно мои соседи с тем же провайдером - у них все работает, и они удивляются и утверждают, что никаких блокировок нет. Тут тоже важно, что у меня статический IP у провайдера уже несколько лет.

Мой коллега по работе попал под блокировку корпоративного (!) OpenVPN внутри (!) РФ , долго мучался, но стоило ему сменить IP у провайдера - все стало ок.