Предыстория
С сентября 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 на сервер:
- Скачать на сервер nfqws - zapret/binaries/x86_64/nfqws at master · bol-van/zapret · GitHub
- Запустить его из под рута в 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 в виде нулей в этом случае не подойдёт. - Добавить правило 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
(диапазон портов сменить, если он у вас другой) - Это заставит сервер отправить 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 в виде нулей, он от этого не крашается.